SavvyCube_Ecommerce_Analytics_Connector - Version 2.0.3

Version Notes

Stable public release

Download this release

Release Info

Developer Webtex Software
Extension SavvyCube_Ecommerce_Analytics_Connector
Version 2.0.3
Comparing to
See all releases


Code changes from version 0.0.7 to 2.0.3

Files changed (75) hide show
  1. app/code/community/SavvyCube/Connector/Block/Config/Activate.php +17 -12
  2. app/code/community/SavvyCube/Connector/Block/Config/Version.php +7 -35
  3. app/code/community/SavvyCube/Connector/CHANGELOG.md +0 -7
  4. app/code/community/SavvyCube/Connector/Helper/Authorization.php +221 -149
  5. app/code/community/SavvyCube/Connector/Helper/Data.php +43 -114
  6. app/code/community/SavvyCube/Connector/Model/Api/Abstract.php +87 -127
  7. app/code/community/SavvyCube/Connector/Model/Api/Category.php +140 -0
  8. app/code/community/SavvyCube/Connector/Model/Api/Customer.php +104 -0
  9. app/code/community/SavvyCube/Connector/Model/Api/Invoice.php +41 -51
  10. app/code/community/SavvyCube/Connector/Model/Api/Invoiceitem.php +22 -31
  11. app/code/community/SavvyCube/Connector/Model/Api/Notification.php +0 -44
  12. app/code/community/SavvyCube/Connector/Model/Api/Order.php +109 -73
  13. app/code/community/SavvyCube/Connector/Model/Api/{Address.php → Orderaddress.php} +20 -39
  14. app/code/community/SavvyCube/Connector/Model/Api/Orderitem.php +52 -71
  15. app/code/community/SavvyCube/Connector/Model/Api/Probe.php +265 -0
  16. app/code/community/SavvyCube/Connector/Model/Api/Product.php +227 -0
  17. app/code/community/SavvyCube/Connector/Model/Api/Quote.php +104 -0
  18. app/code/community/SavvyCube/Connector/Model/Api/Quoteaddress.php +88 -0
  19. app/code/community/SavvyCube/Connector/Model/Api/Quoteitem.php +71 -0
  20. app/code/community/SavvyCube/Connector/Model/Api/Refund.php +36 -42
  21. app/code/community/SavvyCube/Connector/Model/Api/Refunditem.php +22 -30
  22. app/code/community/SavvyCube/Connector/Model/Api/Rewrite.php +62 -0
  23. app/code/community/SavvyCube/Connector/Model/Api/Shipment.php +10 -13
  24. app/code/community/SavvyCube/Connector/Model/Api/Shipmentitem.php +11 -13
  25. app/code/community/SavvyCube/Connector/Model/Api/Transaction.php +19 -20
  26. app/code/community/SavvyCube/Connector/Model/Api/Version.php +0 -58
  27. app/code/community/SavvyCube/Connector/{controllers/Adminhtml/IndexController.php → Model/Baseurl.php} +15 -14
  28. app/code/community/SavvyCube/Connector/Model/Nonce.php +0 -155
  29. app/code/community/SavvyCube/Connector/Model/Resource/Main.php +87 -0
  30. app/code/community/SavvyCube/Connector/cert/x509.crt +0 -25
  31. app/code/community/SavvyCube/Connector/controllers/ApiController.php +66 -180
  32. app/code/community/SavvyCube/Connector/controllers/SavvycubeController.php +65 -0
  33. app/code/community/SavvyCube/Connector/etc/adminhtml.xml +21 -20
  34. app/code/community/SavvyCube/Connector/etc/config.xml +44 -90
  35. app/code/community/SavvyCube/Connector/etc/system.xml +45 -35
  36. app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-install-0.0.1.php +2 -1
  37. app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-install-0.0.9.php +27 -0
  38. app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-install-2.0.0.php +69 -0
  39. app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-upgrade-0.0.4-0.0.5.php +3 -3
  40. app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-upgrade-0.0.8-0.0.9.php +30 -0
  41. app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-upgrade-0.0.9-2.0.0.php +68 -0
  42. app/design/frontend/base/default/layout/wCube/layout.xml +29 -0
  43. app/design/frontend/base/default/template/wCube/ga.phtml +45 -0
  44. app/etc/modules/SavvyCube_Connector.xml +18 -17
  45. lib/sc/connector/vendor/autoload.php +7 -0
  46. lib/sc/connector/vendor/composer/ClassLoader.php +445 -0
  47. lib/sc/connector/vendor/composer/LICENSE +21 -0
  48. lib/sc/connector/vendor/composer/autoload_classmap.php +9 -0
  49. lib/sc/connector/vendor/composer/autoload_files.php +11 -0
  50. lib/sc/connector/vendor/composer/autoload_namespaces.php +14 -0
  51. lib/sc/connector/vendor/composer/autoload_psr4.php +9 -0
  52. lib/sc/connector/vendor/composer/autoload_real.php +74 -0
  53. lib/sc/connector/vendor/composer/autoload_static.php +59 -0
  54. lib/sc/connector/vendor/composer/include_paths.php +10 -0
  55. lib/sc/connector/vendor/composer/installed.json +103 -0
  56. lib/sc/connector/vendor/phpseclib/phpseclib/AUTHORS +6 -0
  57. lib/sc/connector/vendor/phpseclib/phpseclib/LICENSE +21 -0
  58. lib/sc/connector/vendor/phpseclib/phpseclib/README.md +74 -0
  59. lib/sc/connector/vendor/phpseclib/phpseclib/composer.json +81 -0
  60. lib/sc/connector/vendor/phpseclib/phpseclib/composer.lock +1669 -0
  61. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php +197 -0
  62. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php +2611 -0
  63. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php +671 -0
  64. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php +1516 -0
  65. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +861 -0
  66. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php +761 -0
  67. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php +350 -0
  68. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +3133 -0
  69. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php +334 -0
  70. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php +1050 -0
  71. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php +517 -0
  72. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php +881 -0
  73. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php +601 -0
  74. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +1407 -0
  75. lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/File/X509.php +4733 -0
app/code/community/SavvyCube/Connector/Block/Config/Activate.php CHANGED
@@ -14,21 +14,26 @@
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
  class SavvyCube_Connector_Block_Config_Activate
21
- extends Mage_Adminhtml_Block_System_Config_Form_Fieldset
22
  {
23
 
24
- public function render(Varien_Data_Form_Element_Abstract $element)
25
- {
26
- return $this->getLayout()->createBlock('adminhtml/widget_button') //create the add button
27
- ->setData(array(
28
- 'label' => Mage::helper('wCube')->__('Activate Connector / Refresh Activation'),
29
- 'onclick' => "setLocation('".$this->getUrl('wCubeAdmin/adminhtml_index/index')."')",
30
- 'class' => 'task'
31
- ))->toHtml();
32
 
33
- }
34
- }
 
 
 
 
 
 
 
 
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Block_Config_Activate
22
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
23
  {
24
 
25
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
26
+ {
27
+ $this->setElement($element);
28
+ $url = $this->getUrl('catalog/product'); //
 
 
 
 
29
 
30
+ $html = $this->getLayout()->createBlock('adminhtml/widget_button')
31
+ ->setType('button')
32
+ ->setClass('scalable')
33
+ ->setLabel('Connect')
34
+ ->setOnClick("setLocation('".$this->getUrl('adminhtml/savvycube/index')."')")
35
+ ->toHtml();
36
+
37
+ return $html;
38
+ }
39
+ }
app/code/community/SavvyCube/Connector/Block/Config/Version.php CHANGED
@@ -14,46 +14,18 @@
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
  class SavvyCube_Connector_Block_Config_Version
21
- extends Mage_Adminhtml_Block_System_Config_Form_Fieldset_Modules_DisableOutput
22
  {
23
- public function render(Varien_Data_Form_Element_Abstract $element)
24
  {
25
-
26
- $html = $this->_getHeadFieldHtml($element);
27
  /** @var SavvyCube_Connector_Helper_Data $helper */
28
  $helper = Mage::helper('wCube');
29
-
30
- foreach ($helper->getVersionData() as $data) {
31
- $html.= $this->_getFieldHtml($element, $data);
32
- }
33
- $html .= $this->_getFooterHtml($element);
34
-
35
- return $html;
36
  }
37
-
38
- protected function _getHeadFieldHtml($fieldset)
39
- {
40
- $html = '<tr>';
41
- $html .= '<td class="label"/>';
42
- $html .= '<td class="value"/>';
43
- $html .= '</tr>';
44
- return $html;
45
- }
46
-
47
- protected function _getFieldHtml($fieldset, $data)
48
- {
49
- $field = $fieldset->addField((string)$data->id, 'label',
50
- array(
51
- 'name' => $data->id,
52
- 'label' => $data->name,
53
- 'value' => $data->version,
54
- ))->setRenderer($this->_getFieldRenderer());
55
-
56
- return $field->toHtml();
57
- }
58
-
59
- }
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Block_Config_Version
22
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
23
  {
24
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
25
  {
 
 
26
  /** @var SavvyCube_Connector_Helper_Data $helper */
27
  $helper = Mage::helper('wCube');
28
+ $element->setValue($helper->getCurrentModuleVersion());
29
+ return parent::_getElementHtml($element);
 
 
 
 
 
30
  }
31
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/SavvyCube/Connector/CHANGELOG.md DELETED
@@ -1,7 +0,0 @@
1
- 0.0.1
2
- =====
3
- * Initial version.
4
-
5
- 0.0.2
6
- =====
7
- * First stable release
 
 
 
 
 
 
 
app/code/community/SavvyCube/Connector/Helper/Authorization.php CHANGED
@@ -14,175 +14,247 @@
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
  class SavvyCube_Connector_Helper_Authorization extends Mage_Core_Helper_Abstract
21
  {
22
- const CONSUMER_KEY_LENGTH = 10;
23
-
24
- /**
25
- * function generates consumer key, encrypts it and tries to send
26
- * to $consumerEndpoint. Returns operation status.
27
- *
28
- * @return bool
29
- */
30
- public function initConsumerKey()
31
- {
32
- $plainConsumerKey = $this->generateNewKey();
33
- $eKey = $this->generateNewEKey();
34
- $this->setCurrentKey($plainConsumerKey);
35
- $this->setCurrentKey($eKey, 'e');
 
 
 
 
 
 
 
 
 
 
36
  Mage::getConfig()->cleanCache();
37
  Mage::app()->reinitStores();
38
- return true;
39
  }
40
 
41
- /**
42
- * function generates new consumer key
43
- *
44
- * @return string
45
- */
46
- private function generateNewKey()
 
 
 
47
  {
48
- return mcrypt_create_iv(self::CONSUMER_KEY_LENGTH);
49
- }
50
-
51
- /**
52
- * function generates new traffic encryption key
53
- *
54
- * @return string
55
- */
56
- private function generateNewEKey()
57
- {
58
- return mcrypt_create_iv(16);
59
- }
60
-
61
- /**
62
- * function returns certificate path from current module configuration
63
- *
64
- * @return string
65
- */
66
- private function getCert()
67
- {
68
- return
69
- Mage::getModuleDir("", 'SavvyCube_Connector') . DS .
70
- str_replace(
71
- '/',
72
- DS,
73
- (string) Mage::getStoreConfig('wCube/cube_crypt/open_key_file_path')
74
- );
75
- }
76
-
77
- /**
78
- * function generates module activation url
79
- *
80
- * @return string url to activate model
81
- */
82
- public function getActivateUrl()
83
- {
84
- $url = $this->getConsumerEndpoint()
85
- . "datasources/?act=connect&type=0"
86
- . "&url=" . urlencode(Mage::getBaseUrl())
87
- . "&secure_url=" . urlencode(Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true))
88
- . "&key=" . rawurlencode($this->getCurrentEncryptedKey())
89
- . "&e_key=" . rawurlencode($this->getCurrentEncryptedKey('e'));
90
- return $url;
91
- }
92
-
93
- /**
94
- * return consumer endpoint
95
- *
96
- * @return string
97
- */
98
- private function getConsumerEndpoint()
99
- {
100
- return (string) Mage::getStoreConfig('wCube/cube_crypt/consumer_endpoint');
101
- }
102
-
103
- /**
104
- * store consumer secret in configuration with encryption
105
- */
106
- private function setCurrentKey($key, $type = 'consumer')
107
- {
108
- Mage::getConfig()->saveConfig("cube_crypt/{$type}_secret", Mage::helper('core')->encrypt($key));
109
- $rsaProvider = new Zend_Crypt_Rsa(array('certificatePath' => $this->getCert()));
110
- $encryptedKey = $rsaProvider->encrypt($key, $rsaProvider->getPublicKey(), Zend_Crypt_Rsa::BASE64);
111
- Mage::getConfig()->saveConfig("cube_crypt/{$type}_encrypted", $encryptedKey);
112
- }
113
-
114
- /**
115
- * return consumer encrypted secret from configuration in plain text
116
- *
117
- * @return string
118
- */
119
- private function getCurrentEncryptedKey($type = 'consumer')
120
- {
121
- return (string)Mage::getStoreConfig("cube_crypt/{$type}_encrypted");
122
- }
123
-
124
- /**
125
- * return current consumer secret from configuration in plain text
126
- *
127
- * @return string
128
- */
129
- public function getCurrentKey($type = 'consumer')
130
- {
131
- return Mage::helper('core')->decrypt((string)Mage::getStoreConfig("cube_crypt/{$type}_secret"));
132
- }
133
-
134
- /**
135
- * function checks if request is valid
136
- *
137
- * @param Mage_Core_Controller_Request_Http $request request for checking
138
- *
139
- * @return bool
140
- */
141
- public function checkRequest()
142
- {
143
- if (isset($_SERVER['HTTP_X_WSSE'])) {
144
- $xWsse = $this->parseToken($_SERVER['HTTP_X_WSSE']);
145
- if ($xWsse) {
146
- /** @var SavvyCube_Connector_Model_Nonce $nonceModel */
147
- $nonceModel = Mage::getModel('wCube/nonce');
148
- $xWsse['Nonce'] = urldecode($xWsse['Nonce']);
149
- $xWsse['Created'] = urldecode($xWsse['Created']);
150
- if ($nonceModel->checkNonce($xWsse['Nonce'], $xWsse['Created'])) {
151
- $calculatedDigest = base64_encode((sha1($xWsse['Nonce'] . $xWsse['Created'] . $this->getCurrentKey())));
152
- return $calculatedDigest === $xWsse['SecretDigest'];
153
- }
154
- }
155
  }
156
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
- private function parseToken($token)
161
  {
162
- $wsse = '/UsernameToken Username="([^"]+)", SecretDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
163
- if (1 === preg_match($wsse, $token, $matches)) {
164
- array_shift($matches);
165
- $map = array('Username', 'SecretDigest', 'Nonce', 'Created');
166
- return array_combine($map, $matches);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
- return false;
 
169
  }
170
 
171
- /**
172
- * return nonce lifeTime value from current module configuration
173
- *
174
- * @param bool $secondsFormat return in seconds if true given
175
- *
176
- * @return int
177
- */
178
- public function getNonceLifetime($secondsFormat = false)
179
  {
180
- $lifeTimeInMinutes = (string) Mage::getStoreConfig('wCube/cube_crypt/nonce_lifetime');
 
 
 
 
 
181
 
182
- if ($secondsFormat) {
183
- return $lifeTimeInMinutes * 60;
 
 
 
 
 
 
 
 
184
  }
185
 
186
- return $lifeTimeInMinutes;
 
 
 
 
 
 
 
 
 
 
187
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  }
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Helper_Authorization extends Mage_Core_Helper_Abstract
22
  {
23
+ const TIMESTAMP_GAP = 600; # 10 min
24
+
25
+ protected $_scRsa = null;
26
+
27
+ protected $_rsa = null;
28
+
29
+ protected $_cRsa = null;
30
+
31
+ public function getActivationUrl()
32
+ {
33
+ $baseUrl = Mage::getStoreConfig('w_cube/settings/base_url', 0);
34
+ $adminUrl = Mage::helper("adminhtml")
35
+ ->getUrl("adminhtml/savvycube/activate");
36
+ return Mage::getStoreConfig('w_cube/settings/savvy_url')
37
+ . "account/connect-login?"
38
+ . "&type=m1"
39
+ . "&url=" . urlencode($baseUrl)
40
+ . "&admin_url=" . urlencode($adminUrl)
41
+ . "&session=" . Mage::getStoreConfig('w_cube/settings/candidate_ts', 0)
42
+ . "&pub=" . base64_encode($this->getCandidatePublicKey());
43
+ }
44
+
45
+ public function cleanCache()
46
+ {
47
  Mage::getConfig()->cleanCache();
48
  Mage::app()->reinitStores();
 
49
  }
50
 
51
+ public function generateKeys()
52
+ {
53
+ $keys = $this->getRsa()->createKey(2048);
54
+ $this->setCandidatePublicKey($keys['publickey']);
55
+ $this->setCandidatePrivateKey($keys['privatekey']);
56
+ $this->_cRsa = null;
57
+ }
58
+
59
+ public function candidateSignature($session)
60
  {
61
+ $currentTs = (int)Mage::getSingleton('core/date')->gmtTimestamp();
62
+ if ($session == Mage::getStoreConfig('w_cube/settings/candidate_ts', 0)
63
+ && $currentTs - Mage::getStoreConfig('w_cube/settings/candidate_ts', 0) < 120
64
+ ) {
65
+ $rsa = $this->getCandidateRsa();
66
+ $iv = crypt_random_string(10);
67
+ return array(base64_encode($iv),
68
+ base64_encode($rsa->sign($iv)));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
+
71
+ return False;
72
+ }
73
+
74
+ public function promoteCandidateKeys($session)
75
+ {
76
+ $currentTs = (int)Mage::getSingleton('core/date')->gmtTimestamp();
77
+ if ($session == Mage::getStoreConfig('w_cube/settings/candidate_ts', 0)
78
+ && $currentTs - Mage::getStoreConfig('w_cube/settings/candidate_ts', 0) < 120
79
+ ) {
80
+ $this->setPublicKey($this->getCandidatePublicKey());
81
+ $this->setPrivateKey($this->getCandidatePrivateKey());
82
+ $this->setCandidatePublicKey('');
83
+ $this->setCandidatePrivateKey('');
84
+ Mage::getConfig()->saveConfig('w_cube/settings/candidate_ts', 0, 'default', 0);
85
+ $this->_rsa = null;
86
+ $this->_cRsa = null;
87
+ return True;
88
+ }
89
+
90
+ return False;
91
+ }
92
+
93
+ public function getCandidatePublicKey()
94
+ {
95
+ return Mage::getStoreConfig('w_cube/settings/candidate_pub', 0);
96
+ }
97
+
98
+ public function setCandidatePublicKey($val)
99
+ {
100
+ Mage::getConfig()->saveConfig('w_cube/settings/candidate_pub', $val, 'default', 0);
101
+ }
102
+
103
+ public function getCandidatePrivateKey()
104
+ {
105
+ return Mage::helper('core')->decrypt(
106
+ Mage::getStoreConfig('w_cube/settings/candidate_priv', 0)
107
+ );
108
  }
109
 
110
+ public function setCandidatePrivateKey($val)
111
+ {
112
+ $currentTs = (int)Mage::getSingleton('core/date')->gmtTimestamp();
113
+ $val = Mage::helper('core')->encrypt($val);
114
+ Mage::getConfig()->saveConfig('w_cube/settings/candidate_priv', $val, 'default', 0);
115
+ Mage::getConfig()->saveConfig('w_cube/settings/candidate_ts', $currentTs, 'default', 0);
116
+ }
117
+
118
+
119
+ public function getPublicKey()
120
+ {
121
+ return Mage::getStoreConfig('w_cube/settings/pub', 0);
122
+ }
123
 
124
+ public function setPublicKey($val)
125
  {
126
+ Mage::getConfig()->saveConfig('w_cube/settings/pub', $val, 'default', 0);
127
+ }
128
+
129
+ public function getPrivateKey()
130
+ {
131
+ return Mage::getStoreConfig('w_cube/settings/priv', 0);
132
+ }
133
+
134
+ public function setPrivateKey($val)
135
+ {
136
+ $val = Mage::helper('core')->encrypt($val);
137
+ Mage::getConfig()->saveConfig('w_cube/settings/priv', $val, 'default', 0);
138
+ }
139
+
140
+ public function getToken()
141
+ {
142
+ return Mage::getStoreConfig('w_cube/settings/token', 0);
143
+ }
144
+
145
+ public function setToken($token)
146
+ {
147
+ Mage::getConfig()->saveConfig('w_cube/settings/token', $token, 'default', 0);
148
+ }
149
+
150
+ public function registerAutoloader()
151
+ {
152
+ $libDir = Mage::getBaseDir('lib');
153
+ $autoloader = $libDir . DS . implode(DS, array('sc', 'connector', 'vendor', 'autoload.php'));
154
+ return require_once($autoloader);
155
+ }
156
+
157
+
158
+ public function getScRsa()
159
+ {
160
+ if (!isset($this->_scRsa)) {
161
+ $this->registerAutoloader();
162
+ $this->_scRsa = new Crypt_RSA();
163
+ $this->_scRsa->loadKey($this->getToken());
164
+ $this->_scRsa->setSaltLength(128);
165
  }
166
+
167
+ return $this->_scRsa;
168
  }
169
 
170
+ public function getCandidateRsa()
 
 
 
 
 
 
 
171
  {
172
+ if (!isset($this->_cRsa)) {
173
+ $this->registerAutoloader();
174
+ $this->_cRsa = new Crypt_RSA();
175
+ $this->_cRsa->loadKey($this->getCandidatePrivateKey());
176
+ $this->_cRsa->setSaltLength(128);
177
+ }
178
 
179
+ return $this->_cRsa;
180
+ }
181
+
182
+ public function getRsa()
183
+ {
184
+ if (!isset($this->_rsa)) {
185
+ $this->registerAutoloader();
186
+ $this->_rsa = new Crypt_RSA();
187
+ $this->_rsa->loadKey($this->getPrivateKey());
188
+ $this->_rsa->setSaltLength(128);
189
  }
190
 
191
+ return $this->_rsa;
192
+ }
193
+
194
+ public function encrypt($key, $data)
195
+ {
196
+ $this->registerAutoloader();
197
+ $cipher = new Crypt_AES();
198
+ $cipher->setKey($key);
199
+ $iv = crypt_random_string($cipher->getBlockLength() >> 3);
200
+ $cipher->setIV($iv);
201
+ return array($iv, base64_encode($cipher->encrypt($data)));
202
  }
203
+
204
+ public function verifySignature($baseStr, $sig)
205
+ {
206
+ return $this->getScRsa()->verify($baseStr, base64_decode($sig));
207
+ }
208
+
209
+ public function auth($request)
210
+ {
211
+ $baseUrl = Mage::getStoreConfig('w_cube/settings/base_url', 0);
212
+ $method = strtoupper($request->getMethod());
213
+ $url = strtolower(rtrim($baseUrl, '/') . $request->getOriginalPathInfo());
214
+ $paramsBase = array();
215
+ $params = $request->getParams();
216
+ ksort($params, SORT_STRING);
217
+ foreach ($params as $key=>$value) {
218
+ $paramsBase[] = $key . "=" . $value;
219
+ }
220
+
221
+ $paramsBase = implode('&', $paramsBase);
222
+ $nonce = $request->getHeader('SC-NONCE');
223
+ $timestamp = $request->getHeader('SC-TIMESTAMP');
224
+ $sig = $request->getHeader('SC-AUTHORIZATION');
225
+ if ($nonce && $timestamp && $sig) {
226
+ $baseStr = implode('&', array($method, $url, $paramsBase, $nonce, $timestamp));
227
+ return $this->checkTimestamp($timestamp)
228
+ && $this->getResource()->checkNonce($nonce)
229
+ && $this->verifySignature($baseStr, $sig);
230
+ }
231
+
232
+ return False;
233
+ }
234
+
235
+ public function getResource()
236
+ {
237
+ return Mage::getResourceModel('wCube/main');
238
+ }
239
+
240
+ public function checkTimestamp($timestamp)
241
+ {
242
+ $currentTs = (int)Mage::getSingleton('core/date')->gmtTimestamp();
243
+ return abs($currentTs - (int)$timestamp) < self::TIMESTAMP_GAP;
244
+ }
245
+
246
+ public function getKeyBySession($session)
247
+ {
248
+ $key = $this->getResource()->getKeyBySession($session);
249
+ if ($key)
250
+ return $this->cleanKey($key);
251
+ return False;
252
+ }
253
+
254
+ public function cleanKey($key)
255
+ {
256
+ return $this->getRsa()->decrypt(base64_decode($key));
257
+ }
258
+
259
+
260
  }
app/code/community/SavvyCube/Connector/Helper/Data.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,18 +14,17 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
22
  {
23
- private $dbRead;
24
-
25
- private $resource;
26
 
27
- private $tableName;
28
 
29
- const AFFECTED_ORDER_CACHE_PATH = 'savvy_affected_orders';
30
 
31
  /**
32
  * return module log name
@@ -35,7 +33,7 @@ class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
35
  */
36
  public function getErrorLog()
37
  {
38
- return 'wCube-error.log';
39
  }
40
 
41
  public function getCurrentModuleVersion()
@@ -43,39 +41,15 @@ class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
43
  return (string)Mage::getConfig()->getNode()->modules->SavvyCube_Connector->version;
44
  }
45
 
46
- public function getDesiredVersion()
47
- {
48
- $configVersion = Mage::getStoreConfig('wCube/module/desired');
49
- if ($configVersion) {
50
- return $configVersion;
51
- }
52
-
53
- return $this->getCurrentModuleVersion();
54
- }
55
-
56
- public function setDesiredVersion($version)
57
- {
58
- Mage::getConfig()->saveConfig('wCube/module/desired', $version);
59
- Mage::getConfig()->reinit();
60
- Mage::app()->reinitStores();
61
- }
62
-
63
  public function getVersionData()
64
  {
65
  return array(
66
  new Varien_Object(
67
  array(
68
  'id' => 'current_version',
69
- 'name' => 'Current Module Version',
70
  'version' => $this->getCurrentModuleVersion()
71
  )
72
- ),
73
- new Varien_Object(
74
- array(
75
- 'id' => 'desired_version',
76
- 'name' => 'Required Version',
77
- 'version' => $this->getDesiredVersion()
78
- )
79
  )
80
  );
81
  }
@@ -91,77 +65,6 @@ class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
91
  );
92
  }
93
 
94
- public function getAffectedOrdersIds($fromDate = false, $toDate = false)
95
- {
96
- $affectedOrders = Mage::app()->getCache()->load(self::AFFECTED_ORDER_CACHE_PATH);
97
- if ($affectedOrders) {
98
- $affectedOrders = unserialize($affectedOrders);
99
- }
100
- if (!$affectedOrders || $affectedOrders['from_date'] != $fromDate || $affectedOrders['to_date'] != $toDate) {
101
- $affectedOrders = array();
102
- $affectedOrders['from_date'] = $fromDate;
103
- $affectedOrders['to_date'] = $toDate;
104
- $affectedOrders['ids'] = array();
105
- $conditions = array();
106
- $bind = array();
107
- if ($fromDate) {
108
- $conditions[] = "updated_at > :fromDate";
109
- $bind[":fromDate"] = $fromDate;
110
- }
111
- if ($fromDate) {
112
- $conditions[] = "updated_at <= :toDate";
113
- $bind[":toDate"] = $toDate;
114
- }
115
-
116
- /** @var Mage_Core_Model_Resource $resource */
117
- $resource = Mage::getSingleton('core/resource');
118
- $connection = $resource->getConnection('core_read');
119
- /** ordered */
120
-
121
- $union = array();
122
- $union[] = $connection->select()
123
- ->from(array('ordered' => $this->getTableName('sales_flat_order')))
124
- ->reset(Zend_Db_Select::COLUMNS)
125
- ->columns(array('order_id' => 'entity_id'));
126
-
127
- /** invoices */
128
- $union[] = $connection->select()
129
- ->from(array('invoices' => $this->getTableName('sales_flat_invoice')))
130
- ->reset(Zend_Db_Select::COLUMNS)
131
- ->columns(array('order_id'));
132
-
133
- /** shipments */
134
- $union[] = $connection->select()
135
- ->from(array('shipments' => $this->getTableName('sales_flat_shipment')))
136
- ->reset(Zend_Db_Select::COLUMNS)
137
- ->columns(array('order_id'));
138
-
139
- /** refunds */
140
- $union[] = $connection->select()
141
- ->from(array('refunds' => $this->getTableName('sales_flat_creditmemo')))
142
- ->reset(Zend_Db_Select::COLUMNS)
143
- ->columns(array('order_id'));
144
-
145
- foreach ($union as $query) {
146
- foreach ($conditions as $condition) {
147
- $query->where($condition);
148
- }
149
- }
150
-
151
- $affectedSql = $connection->select()->union($union);
152
-
153
- foreach ($connection->fetchAll($affectedSql, $bind) as $row) {
154
- if (isset($row['order_id']) && !in_array($row['order_id'], $affectedOrders)) {
155
- $affectedOrders['ids'][] = $row['order_id'];
156
- }
157
- }
158
-
159
- Mage::app()->getCache()->save(serialize($affectedOrders), self::AFFECTED_ORDER_CACHE_PATH);
160
- }
161
-
162
- return $affectedOrders['ids'];
163
- }
164
-
165
  /**
166
  * get db read adapter
167
  *
@@ -169,10 +72,11 @@ class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
169
  */
170
  public function getDbRead()
171
  {
172
- if (!$this->dbRead) {
173
- $this->dbRead = $this->getResource()->getConnection('core_read');
174
  }
175
- return $this->dbRead;
 
176
  }
177
 
178
  /**
@@ -182,10 +86,11 @@ class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
182
  */
183
  public function getResource()
184
  {
185
- if (!$this->resource) {
186
- $this->resource = Mage::getSingleton('core/resource');
187
  }
188
- return $this->resource;
 
189
  }
190
 
191
  /**
@@ -197,9 +102,33 @@ class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
197
  */
198
  public function getTableName($name)
199
  {
200
- if (!isset($this->tableName[$name])) {
201
- $this->tableName[$name] = $this->getResource()->getTableName($name);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  }
203
- return $this->tableName[$name];
 
 
204
  }
205
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Helper_Data extends Mage_Core_Helper_Abstract
22
  {
23
+ protected $_dbRead;
 
 
24
 
25
+ protected $_resource;
26
 
27
+ protected $_tableName;
28
 
29
  /**
30
  * return module log name
33
  */
34
  public function getErrorLog()
35
  {
36
+ return 'wcube-error.log';
37
  }
38
 
39
  public function getCurrentModuleVersion()
41
  return (string)Mage::getConfig()->getNode()->modules->SavvyCube_Connector->version;
42
  }
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  public function getVersionData()
45
  {
46
  return array(
47
  new Varien_Object(
48
  array(
49
  'id' => 'current_version',
50
+ 'name' => 'Connector version:',
51
  'version' => $this->getCurrentModuleVersion()
52
  )
 
 
 
 
 
 
 
53
  )
54
  );
55
  }
65
  );
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  /**
69
  * get db read adapter
70
  *
72
  */
73
  public function getDbRead()
74
  {
75
+ if (!$this->_dbRead) {
76
+ $this->_dbRead = $this->getResource()->getConnection('core_read');
77
  }
78
+
79
+ return $this->_dbRead;
80
  }
81
 
82
  /**
86
  */
87
  public function getResource()
88
  {
89
+ if (!$this->_resource) {
90
+ $this->_resource = Mage::getSingleton('core/resource');
91
  }
92
+
93
+ return $this->_resource;
94
  }
95
 
96
  /**
102
  */
103
  public function getTableName($name)
104
  {
105
+ if (!isset($this->_tableName[$name])) {
106
+ $this->_tableName[$name] = $this->getResource()->getTableName($name);
107
+ }
108
+
109
+ return $this->_tableName[$name];
110
+ }
111
+
112
+ public function getFullCategoryPath($categoryId)
113
+ {
114
+ $category = Mage::getModel('catalog/category')->load($categoryId);
115
+ $result = "";
116
+ if ($category->getId()) {
117
+ $categories = Mage::getModel('catalog/category')
118
+ ->getCollection()
119
+ ->addAttributeToSelect('name')
120
+ ->addAttributeToFilter('entity_id', array('in' => $category->getPathIds()))
121
+ ->getItems();
122
+ foreach ($category->getPathIds() as $id) {
123
+ if (isset($categories[$id])) {
124
+ $result .= $categories[$id]['name'] . "/";
125
+ } else {
126
+ $result .= 'Unknown' . "/";
127
+ }
128
+ };
129
  }
130
+
131
+ return $result;
132
+
133
  }
134
+ }
app/code/community/SavvyCube/Connector/Model/Api/Abstract.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,20 +14,27 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  abstract class SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- const EXISTENCE_PREFIX = 'wcube_if_exists';
 
 
 
 
24
 
25
- protected $request;
26
 
27
- protected $mainTable = '';
28
 
29
- protected $versionColumns = array();
30
 
31
- protected $parentEntity = array();
 
 
32
 
33
  /**
34
  * Render response
@@ -37,38 +43,32 @@ abstract class SavvyCube_Connector_Model_Api_Abstract
37
  */
38
  public function getMethod()
39
  {
40
- if (!empty($this->parentEntity)) {
41
- /** @var SavvyCube_Connector_Model_Api_Abstract $parentModel */
42
- $parentModel = Mage::getModel($this->parentEntity['model']);
43
- $affectedParent = $parentModel->generateQuery()->columns('entity_id');
44
- $this->applyDateLimit($affectedParent, $this->parentEntity['parent_date']);
45
- $affectedParentIds = $this->getHelper()->getDbRead()->fetchAll(
46
- $affectedParent,
47
- $affectedParent->getBind(),
48
- Zend_Db::FETCH_COLUMN
 
49
  );
50
-
51
- if (count($affectedParentIds)) {
52
- return $this->getResult(
53
- $this->generateQuery()
54
- ->columns($this->columnsListForGet())
55
- ->where("`main_table`.{$this->parentEntity['parent_fk']} in (?)", $affectedParentIds)
56
- );
57
- } else {
58
- return array();
59
- }
60
  } else {
61
- $sql = $this->generateQuery()
62
- ->columns($this->columnsListForGet());
63
-
64
- return $this->getResult($sql, '`main_table`.updated_at');
 
65
  }
66
  }
67
 
68
  public function generateQuery()
69
  {
70
  return $this->getHelper()->getDbRead()->select()
71
- ->from(array('main_table' => $this->getHelper()->getTableName($this->mainTable)))
 
72
  ->reset(Varien_Db_Select::COLUMNS);
73
  }
74
 
@@ -80,69 +80,51 @@ abstract class SavvyCube_Connector_Model_Api_Abstract
80
  {
81
  $bind = array();
82
 
83
- $fromDate = false;
84
- $toDate = false;
85
-
86
- if ($this->request['from_date'] !== null) {
87
- $fromDate = urldecode($this->request['from_date']);
88
- }
89
- if ($this->request['to_date'] !== null) {
90
- $toDate = urldecode($this->request['to_date']);
91
  }
92
 
93
- $conditions = array();
94
- if ($fromDate) {
95
- $conditions[] = "{$dateColumn} > :fromDate";
96
- $bind[":fromDate"] = $fromDate;
97
- }
98
- if ($fromDate) {
99
- $conditions[] = "{$dateColumn} <= :toDate";
100
- $bind[":toDate"] = $toDate;
101
  }
102
 
103
- foreach ($conditions as $condition) {
104
- $query->where($condition);
105
- }
106
  $query->bind(array_merge($query->getBind(), $bind));
107
  }
108
 
109
  /**
110
- * init model and set $request array
111
  *
112
- * @param array $request
113
  *
114
  * @return $this
115
  */
116
- public function init($request)
117
  {
118
- $this->request = $request;
 
 
 
 
119
  return $this;
120
  }
121
 
122
- /**
123
- * init sql select with order status date filter
124
- *
125
- * @return Varien_Db_Select
126
- */
127
- protected function getAffectedOrders()
128
  {
129
- $fromDate = false;
130
- $toDate = false;
131
-
132
- if ($this->request['from_date'] !== null) {
133
- $fromDate = urldecode($this->request['from_date']);
134
- }
135
- if ($this->request['to_date'] !== null) {
136
- $toDate = urldecode($this->request['to_date']);
137
- }
138
-
139
- if (!$fromDate && !$toDate) {
140
- return true;
141
- } else {
142
- /** @var SavvyCube_Connector_Helper_Data $helper */
143
- $helper = Mage::helper('wCube');
144
- return $helper->getAffectedOrdersIds($fromDate, $toDate);
145
- }
146
  }
147
 
148
  protected function getResult($query, $dateColumn = false)
@@ -150,8 +132,13 @@ abstract class SavvyCube_Connector_Model_Api_Abstract
150
  if ($dateColumn) {
151
  $this->applyDateLimit($query, $dateColumn);
152
  }
 
153
  $this->renderParameters($query);
154
- return $this->getHelper()->getDbRead()->fetchAll($query, $query->getBind());
 
 
 
 
155
  }
156
 
157
  /**
@@ -161,8 +148,8 @@ abstract class SavvyCube_Connector_Model_Api_Abstract
161
  */
162
  protected function renderParameters($sql)
163
  {
164
- if ($this->request['count'] !== null && $this->request['offset'] !== null) {
165
- $sql->limit($this->request['count'], $this->request['offset']);
166
  }
167
  }
168
 
@@ -174,68 +161,41 @@ abstract class SavvyCube_Connector_Model_Api_Abstract
174
  return Mage::helper('wCube');
175
  }
176
 
 
 
 
 
 
177
  /**
178
  * Return columns list for getMethod select
179
  *
180
  * @return string | array
181
  */
182
- protected function columnsListForGet()
183
  {
184
  return '*';
185
  }
186
 
187
- public function prepareColumns($columns, $tableAlias = false)
188
  {
189
  $result = array();
190
- foreach ($columns as $key => $column) {
191
- if (is_string($key)) {
192
- $columnAlias = $key;
193
- }
194
- if (isset($this->versionColumns[$column])) {
195
- $versionInfo = $this->versionColumns[$column];
196
- if (isset($versionInfo['check_existence']) && !$this->checkColumn($this->mainTable, $column)
197
- || isset($versionInfo['since']) && Mage::getVersion() < $versionInfo['since']
198
- ) {
199
- /** skip missing columns */
200
- continue;
201
- } elseif (isset($versionInfo['renamed']) && Mage::getVersion() < $versionInfo['renamed']['since']) {
202
- if (!isset($columnAlias)) {
203
- $columnAlias = $column;
204
- }
205
- $column = $versionInfo['renamed']['originally'];
206
- }
207
- }
208
- if (!isset($columnAlias)) {
209
- $columnAlias = $column;
210
- }
211
- if ($tableAlias) {
212
- $column = "{$tableAlias}.{$column}";
213
- }
214
-
215
- $result[$columnAlias] = $column;
216
- unset($columnAlias);
217
- }
218
- return $result;
219
- }
220
-
221
- public function checkColumn($table, $columnName)
222
- {
223
- $result = Mage::app()->getCache()->load(self::EXISTENCE_PREFIX . $table . $columnName);
224
- if (!$result) {
225
- $columns = $this->getHelper()->getDbRead()->describeTable(
226
- $this->getHelper()->getTableName($this->mainTable)
227
  );
228
- $result = '';
229
- foreach ($columns as $column) {
230
- if ($column['COLUMN_NAME'] == $columnName) {
231
- $result = $columnName;
232
- break;
 
 
 
233
  }
234
  }
235
-
236
- Mage::app()->getCache()->save($result, self::EXISTENCE_PREFIX . $table . $columnName);
237
  }
238
 
239
- return $result == $columnName;
240
  }
241
  }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  abstract class SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_request;
24
+
25
+ protected $_queryTime = 0;
26
+
27
+ protected $_count = 0;
28
 
29
+ protected $_data = null;
30
 
31
+ protected $_mainTable = '';
32
 
33
+ protected $_parentEntity = array();
34
 
35
+ protected $_order = 'main_table.entity_id';
36
+
37
+ public $error = null;
38
 
39
  /**
40
  * Render response
43
  */
44
  public function getMethod()
45
  {
46
+ if (!empty($this->_parentEntity)) {
47
+ $this->_data = $this->getResult(
48
+ $this->generateQuery()
49
+ ->joinLeft(
50
+ array('parent_table' => $this->_parentEntity['table']),
51
+ "parent_table.entity_id = main_table.{$this->_parentEntity['parent_fk']}"
52
+ )
53
+ ->reset(Varien_Db_Select::COLUMNS)
54
+ ->columns($this->columnsListForGet()),
55
+ 'parent_table.updated_at'
56
  );
57
+ return true;
 
 
 
 
 
 
 
 
 
58
  } else {
59
+ $this->_data = $this->getResult(
60
+ $this->generateQuery()->columns($this->columnsListForGet()),
61
+ '`main_table`.updated_at'
62
+ );
63
+ return true;
64
  }
65
  }
66
 
67
  public function generateQuery()
68
  {
69
  return $this->getHelper()->getDbRead()->select()
70
+ ->from(array('main_table' => $this->getHelper()->getTableName($this->_mainTable)))
71
+ ->order($this->_order)
72
  ->reset(Varien_Db_Select::COLUMNS);
73
  }
74
 
80
  {
81
  $bind = array();
82
 
83
+ if (isset($this->_request['from'])) {
84
+ $query->where("{$dateColumn} >= :fromDate");
85
+ $bind[":fromDate"] = $this->_request['from'];
 
 
 
 
 
86
  }
87
 
88
+ if (isset($this->_request['to'])) {
89
+ $query->where("{$dateColumn} <= :toDate");
90
+ $bind[":toDate"] = $this->_request['to'];
 
 
 
 
 
91
  }
92
 
 
 
 
93
  $query->bind(array_merge($query->getBind(), $bind));
94
  }
95
 
96
  /**
97
+ * init model and set $_request array
98
  *
99
+ * @param array $params
100
  *
101
  * @return $this
102
  */
103
+ public function init($params)
104
  {
105
+ $this->_request = array();
106
+ $this->_request['offset'] = array_key_exists('offset', $params) ? $params['offset'] : 0;
107
+ $this->_request['count'] = array_key_exists('count', $params) ? $params['count'] : 100;
108
+ $this->_request['from'] = array_key_exists('from', $params) ? urldecode($params['from']) : null;
109
+ $this->_request['to'] = array_key_exists('to', $params) ? urldecode($params['to']) : null;
110
  return $this;
111
  }
112
 
113
+ public function formatResponse($key)
 
 
 
 
 
114
  {
115
+ Mage::app()->getResponse()->setHeader(
116
+ 'sc-version',
117
+ $this->getHelper()->getCurrentModuleVersion()
118
+ );
119
+ Mage::app()->getResponse()->setHeader('sc-query-time', $this->_queryTime);
120
+ Mage::app()->getResponse()->setHeader('sc-report-count', $this->_count);
121
+ $options = 0;
122
+ $data = json_encode($this->_data, $options);
123
+ list($iv, $encryptedData) = $this->getAuthHelper()->encrypt($key, $data);
124
+ $signature = $this->getAuthHelper()->getRsa()->sign($encryptedData);
125
+ Mage::app()->getResponse()->setHeader('Sc-Sig', base64_encode($signature));
126
+ Mage::app()->getResponse()->setHeader('Sc-Iv', base64_encode($iv));
127
+ Mage::app()->getResponse()->setBody($encryptedData);
 
 
 
 
128
  }
129
 
130
  protected function getResult($query, $dateColumn = false)
132
  if ($dateColumn) {
133
  $this->applyDateLimit($query, $dateColumn);
134
  }
135
+
136
  $this->renderParameters($query);
137
+ $start = microtime(true);
138
+ $report = $this->getHelper()->getDbRead()->fetchAll($query, $query->getBind());
139
+ $this->_count = count($report);
140
+ $this->_queryTime += microtime(true) - $start;
141
+ return $report;
142
  }
143
 
144
  /**
148
  */
149
  protected function renderParameters($sql)
150
  {
151
+ if (isset($this->_request['count']) && isset($this->_request['offset'])) {
152
+ $sql->limit($this->_request['count'], $this->_request['offset']);
153
  }
154
  }
155
 
161
  return Mage::helper('wCube');
162
  }
163
 
164
+ protected function getAuthHelper()
165
+ {
166
+ return Mage::helper('wCube/authorization');
167
+ }
168
+
169
  /**
170
  * Return columns list for getMethod select
171
  *
172
  * @return string | array
173
  */
174
+ public function columnsListForGet()
175
  {
176
  return '*';
177
  }
178
 
179
+ public function prepareColumns($columns, $table, $tableAlias = false, $aliases = array())
180
  {
181
  $result = array();
182
+ $columns = array_flip($columns);
183
+ if ($this->getHelper()->getDbRead()->isTableExists($table)) {
184
+ $tableDescription = $this->getHelper()->getDbRead()->describeTable(
185
+ $this->getHelper()->getTableName($table)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  );
187
+ foreach ($tableDescription as $column) {
188
+ if (isset($columns[$column['COLUMN_NAME']])) {
189
+ $result[isset($aliases[$column['COLUMN_NAME']])
190
+ ? $aliases[$column['COLUMN_NAME']]
191
+ : $column['COLUMN_NAME']]
192
+ = $tableAlias
193
+ ? "{$tableAlias}.{$column['COLUMN_NAME']}"
194
+ : $column['COLUMN_NAME'];
195
  }
196
  }
 
 
197
  }
198
 
199
+ return $result;
200
  }
201
  }
app/code/community/SavvyCube/Connector/Model/Api/Category.php ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Category extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+
24
+ protected $_categories;
25
+
26
+ public function getMethod()
27
+ {
28
+ $result = array();
29
+ $count = (int)$this->_request['count'];
30
+ $offset = (int)$this->_request['offset'];
31
+ $storeId = (int)$this->_request['store'];
32
+ $store = Mage::app()->getStore($storeId);
33
+ $initialEnvironmentInfo = Mage::getSingleton('core/app_emulation')->startEnvironmentEmulation($store->getId());
34
+
35
+ $categoryCollection = Mage::getModel('catalog/category')
36
+ ->getCollection()
37
+ ->addAttributeToSelect('created_at')
38
+ ->addAttributeToSelect('updated_at');
39
+ if (isset($this->_request['from'])) {
40
+ $categoryCollection->getSelect()
41
+ ->where(
42
+ "updated_at >= ?",
43
+ $this->_request['from']
44
+ );
45
+ }
46
+
47
+ if (isset($this->_request['to'])) {
48
+ $categoryCollection->getSelect()
49
+ ->where(
50
+ "updated_at <= ?",
51
+ $this->_request['to']
52
+ );
53
+ }
54
+
55
+ $start = microtime(true);
56
+ $categories = $categoryCollection->getItems();
57
+ $this->_queryTime += microtime(true) - $start;
58
+
59
+ foreach ($categories as $id => $category) {
60
+ $result[$id] = $this->processCategory(
61
+ $category,
62
+ $store
63
+ );
64
+ }
65
+
66
+ Mage::getSingleton('core/app_emulation')->stopEnvironmentEmulation($initialEnvironmentInfo);
67
+
68
+ $this->_count = count($result);
69
+ $this->_data = $result;
70
+ return true;
71
+ }
72
+
73
+ protected function processCategory($category, $store)
74
+ {
75
+ $result['entity_id'] = $category->getEntityId();
76
+ $result['store_id'] = $store->getId();
77
+ $result['name'] = $this->getFullCategoryPath($category->getId(), $store);
78
+ $result['created_at'] = $category->getCreatedAt();
79
+ $result['updated_at'] = $category->getUpdatedAt();
80
+ return $result;
81
+ }
82
+
83
+ protected function getFullCategoryPath($catId, $store)
84
+ {
85
+ $result = array();
86
+ if (!isset($this->_categories[$store->getId()])) {
87
+ $collection = Mage::getModel('catalog/category')->getCollection()
88
+ ->setStoreId($store->getId())
89
+ ->addAttributeToSelect('name');
90
+ $orFilter = array();
91
+ if ($store->getRootCategoryId() != 0) {
92
+ $rootCategory = $store->getRootCategoryId();
93
+ $orFilter[] = array('attribute' => 'path', 'like' => "1/{$rootCategory}");
94
+ $orFilter[] = array('attribute' => 'path', 'like' => "1/{$rootCategory}/%");
95
+ $orFilter[] = array('attribute' => 'parent_id', 'eq' => 0);
96
+ $collection->addAttributeToFilter($orFilter);
97
+ }
98
+
99
+ $this->_categories[$store->getId()] = $collection->getItems();
100
+ }
101
+
102
+ $categories = $this->_categories[$store->getId()];
103
+ if (isset($categories[$catId])) {
104
+ foreach ($categories[$catId]->getPathIds() as $id) {
105
+ if (isset($categories[$id])) {
106
+ $result[] = $categories[$id]->getName();
107
+ } else {
108
+ $result[] = 'Unknown';
109
+ }
110
+ }
111
+ }
112
+
113
+ if (isset($categories[$store->getRootCategoryId()])) {
114
+ $rootCategory = $categories[$store->getRootCategoryId()];
115
+ foreach ($rootCategory->getPathIds() as $id) {
116
+ if (isset($categories[$id])) {
117
+ $prefix = $categories[$id]->getName();
118
+ } else {
119
+ $prefix = 'Unknown';
120
+ }
121
+
122
+ if (!empty($result) && $result[0] == $prefix) {
123
+ array_shift($result);
124
+ } else {
125
+ break;
126
+ }
127
+ }
128
+ }
129
+
130
+ return implode('/', $result);
131
+ }
132
+
133
+ public function init($params)
134
+ {
135
+ parent::init($params);
136
+ $this->_request['store'] = array_key_exists('store', $params) ? $params['store'] : 0;
137
+ return $this;
138
+ }
139
+
140
+ }
app/code/community/SavvyCube/Connector/Model/Api/Customer.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Customer extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+
24
+ protected $_genderText;
25
+
26
+
27
+ public function getMethod()
28
+ {
29
+ $result = array();
30
+ $customerCollection = Mage::getModel('customer/customer')
31
+ ->getCollection();
32
+
33
+ $count = (int)$this->_request['count'];
34
+ $offset = (int)$this->_request['offset'];
35
+
36
+ $customerCollection->removeAttributeToSelect()
37
+ ->addAttributeToSelect('entity_id')
38
+ ->addAttributeToSelect('website_id')
39
+ ->addAttributeToSelect('gender')
40
+ ->addAttributeToSelect('updated_at')
41
+ ->addAttributeToSelect('created_at')
42
+ ->joinTable(
43
+ array('group' => 'customer/customer_group'),
44
+ 'customer_group_id=group_id',
45
+ array('customer_group' => 'customer_group_code'),
46
+ null,
47
+ 'left'
48
+ );
49
+
50
+ $customerCollection->getSelect()->limit($count, $offset);
51
+
52
+ $dateColumn = 'updated_at';
53
+
54
+ if (isset($this->_request['from'])) {
55
+ $customerCollection->addAttributeToFilter(
56
+ $dateColumn,
57
+ array('gteq' => $this->_request['from'])
58
+ );
59
+ }
60
+
61
+ if (isset($this->_request['to'])) {
62
+ $customerCollection->addAttributeToFilter(
63
+ $dateColumn,
64
+ array('lt' => $this->_request['to'])
65
+ );
66
+ }
67
+
68
+ $start = microtime(true);
69
+ $customers = $customerCollection->getItems();
70
+ $this->_queryTime += microtime(true) - $start;
71
+
72
+ foreach ($customers as $customerId => $customer) {
73
+ $result[$customerId] = $this->parseCustomer($customer);
74
+ }
75
+
76
+ $this->_count = count($result);
77
+ $this->_data = $result;
78
+ return true;
79
+ }
80
+
81
+ protected function parseCustomer($customer)
82
+ {
83
+
84
+ $result['entity_id'] = $customer->getEntityId();
85
+ $result['gender'] = $this->getGenderText($customer->getGender());
86
+ $result['customer_group'] = $customer->getCustomerGroup();
87
+ $result['updated_at'] = $customer->getUpdatedAt();
88
+ $result['created_at'] = $customer->getCreatedAt();
89
+ return $result;
90
+ }
91
+
92
+ protected function getGenderText($genderValue)
93
+ {
94
+ if (!isset($this->genderTex[$genderValue])) {
95
+ $this->_genderText[$genderValue] =
96
+ Mage::getResourceModel('customer/customer')
97
+ ->getAttribute('gender')
98
+ ->getSource()
99
+ ->getOptionText($genderValue);
100
+ }
101
+
102
+ return $this->_genderText[$genderValue];
103
+ }
104
+ }
app/code/community/SavvyCube/Connector/Model/Api/Invoice.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,69 +14,60 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Invoice extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_invoice';
24
-
25
- protected $versionColumns = array(
26
- 'discount_description' => array(
27
- 'check_existence' => true
28
- ),
29
- 'base_total_refunded' => array(
30
- 'since' => '1.6.0.0'
31
- ),
32
- 'base_shipping_hidden_tax_amnt' => array(
33
- 'renamed' => array(
34
- 'since' => '1.6.0.0',
35
- 'originally' => 'base_shipping_hidden_tax_amount'
36
- )
37
- )
38
- );
39
 
40
  /**
41
  * Return columns list for getMethod select
42
  *
43
  * @return string | array
44
  */
45
- protected function columnsListForGet()
46
  {
47
  return $this->prepareColumns(
48
  array(
49
- 'entity_id',
50
- 'base_grand_total',
51
- 'base_tax_amount',
52
- 'store_to_order_rate',
53
- 'base_shipping_tax_amount',
54
- 'base_discount_amount',
55
- 'base_to_order_rate',
56
- 'store_to_base_rate',
57
- 'base_shipping_amount',
58
- 'total_qty',
59
- 'base_to_global_rate',
60
- 'base_subtotal',
61
- 'billing_address_id',
62
- 'is_used_for_refund',
63
- 'order_id',
64
- 'state',
65
- 'shipping_address_id',
66
- 'store_currency_code',
67
- 'transaction_id',
68
- 'order_currency_code',
69
- 'base_currency_code',
70
- 'global_currency_code',
71
- 'increment_id',
72
- 'created_at',
73
- 'updated_at',
74
- 'base_hidden_tax_amount',
75
- 'base_shipping_hidden_tax_amnt',
76
- 'base_shipping_incl_tax',
77
- 'base_total_refunded',
78
- 'discount_description',
79
  ),
80
- 'main_table'
 
 
 
 
 
 
 
 
 
 
 
 
81
  );
82
  }
83
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Invoice extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_invoice';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  /**
26
  * Return columns list for getMethod select
27
  *
28
  * @return string | array
29
  */
30
+ public function columnsListForGet()
31
  {
32
  return $this->prepareColumns(
33
  array(
34
+ 'base_discount_amount',
35
+ 'base_hidden_tax_amount',
36
+ 'base_shipping_hidden_tax_amnt',
37
+ 'base_shipping_hidden_tax_amount',
38
+ 'base_tax_amount',
39
+ 'base_shipping_tax_amount',
40
+ 'base_shipping_amount',
41
+ 'base_subtotal',
42
+ 'base_grand_total',
43
+ 'base_currency_code',
44
+ 'base_to_global_rate',
45
+ 'base_to_order_rate',
46
+ 'global_currency_code',
47
+ 'order_currency_code',
48
+ 'store_currency_code',
49
+ 'store_to_base_rate',
50
+ 'store_to_order_rate',
51
+ 'entity_id',
52
+ 'increment_id',
53
+ 'order_id',
54
+ 'transaction_id',
55
+ 'created_at',
56
+ 'updated_at',
 
 
 
 
 
 
 
57
  ),
58
+ $this->_mainTable,
59
+ 'main_table',
60
+ array(
61
+ 'base_discount_amount' => 'discount_amount',
62
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
63
+ 'base_shipping_hidden_tax_amnt' => 'shipping_hidden_tax_amnt',
64
+ 'base_shipping_hidden_tax_amount' => 'shipping_hidden_tax_amnt',
65
+ 'base_tax_amount' => 'tax_amount',
66
+ 'base_shipping_tax_amount' => 'shipping_tax_amount',
67
+ 'base_shipping_amount' => 'shipping_amount',
68
+ 'base_subtotal' => 'subtotal',
69
+ 'base_grand_total' => 'grand_total',
70
+ )
71
  );
72
  }
73
+ }
app/code/community/SavvyCube/Connector/Model/Api/Invoiceitem.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,26 +14,16 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Invoiceitem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_invoice_item';
24
-
25
- protected $versionColumns = array(
26
-
27
- 'base_weee_tax_applied_row_amnt' => array(
28
- 'renamed' => array(
29
- 'since' => '1.6.0.0',
30
- 'originally' => 'base_weee_tax_applied_row_amount'
31
- )
32
- )
33
- );
34
 
35
- protected $parentEntity = array(
36
- 'model' => 'wCube/api_invoice',
37
- 'parent_date' => 'updated_at',
38
  'parent_fk' => 'parent_id'
39
  );
40
 
@@ -43,29 +32,31 @@ class SavvyCube_Connector_Model_Api_Invoiceitem extends SavvyCube_Connector_Mode
43
  *
44
  * @return string | array
45
  */
46
- protected function columnsListForGet()
47
  {
48
  return $this->prepareColumns(
49
  array(
50
- 'entity_id',
51
- 'parent_id',
52
- 'base_price',
53
- 'base_row_total',
54
  'base_discount_amount',
 
55
  'base_tax_amount',
56
- 'base_price_incl_tax',
57
  'qty',
 
 
58
  'base_cost',
59
- 'base_row_total_incl_tax',
60
- 'product_id',
61
  'order_item_id',
62
- 'base_hidden_tax_amount',
63
- 'base_weee_tax_applied_amount',
64
- 'base_weee_tax_applied_row_amnt',
65
- 'base_weee_tax_disposition',
66
- 'base_weee_tax_row_disposition',
67
  ),
68
- 'main_table'
 
 
 
 
 
 
 
 
 
69
  );
70
  }
71
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Invoiceitem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_invoice_item';
 
 
 
 
 
 
 
 
 
 
24
 
25
+ protected $_parentEntity = array(
26
+ 'table' => 'sales_flat_invoice',
 
27
  'parent_fk' => 'parent_id'
28
  );
29
 
32
  *
33
  * @return string | array
34
  */
35
+ public function columnsListForGet()
36
  {
37
  return $this->prepareColumns(
38
  array(
 
 
 
 
39
  'base_discount_amount',
40
+ 'base_hidden_tax_amount',
41
  'base_tax_amount',
 
42
  'qty',
43
+ 'base_price',
44
+ 'base_row_total',
45
  'base_cost',
46
+ 'entity_id',
 
47
  'order_item_id',
48
+ 'parent_id'
 
 
 
 
49
  ),
50
+ $this->_mainTable,
51
+ 'main_table',
52
+ array(
53
+ 'base_discount_amount' => 'discount_amount',
54
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
55
+ 'base_tax_amount' => 'tax_amount',
56
+ 'base_price' => 'price',
57
+ 'base_row_total' => 'row_total',
58
+ 'base_cost' => 'cost',
59
+ )
60
  );
61
  }
62
+ }
app/code/community/SavvyCube/Connector/Model/Api/Notification.php DELETED
@@ -1,44 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Magento
5
- *
6
- * NOTICE OF LICENSE
7
- *
8
- * This source file is subject to the Open Software License (OSL 3.0)
9
- * that is bundled with this package in the file LICENSE.txt.
10
- * It is also available through the world-wide-web at this URL:
11
- * http://opensource.org/licenses/osl-3.0.php
12
- * If you did not receive a copy of the license and are unable to
13
- * obtain it through the world-wide-web, please send an email
14
- * to license@savvycube.com so we can send you a copy immediately.
15
- *
16
- * @category SavvyCube
17
- * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
19
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
- */
21
- class SavvyCube_Connector_Model_Api_Notification extends SavvyCube_Connector_Model_Api_Abstract
22
- {
23
-
24
-
25
- /**
26
- * Render response on wCube/api/version get query
27
- *
28
- * @return array
29
- */
30
- public function getMethod()
31
- {
32
- /** @var SavvyCube_Connector_Helper_Data $helper */
33
- $helper = Mage::helper('wCube');
34
- $helper->addAdminNotification(
35
- $this->request['title'],
36
- $this->request['description']
37
- );
38
-
39
- return array(
40
- 'success' => 1
41
- );
42
- }
43
-
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/SavvyCube/Connector/Model/Api/Order.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,24 +14,13 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Order extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_order';
24
-
25
- protected $versionColumns = array(
26
- 'coupon_rule_name' => array(
27
- 'since' => '1.6.0.7'
28
- ),
29
- 'base_shipping_hidden_tax_amnt' => array(
30
- 'renamed' => array(
31
- 'since' => '1.6.0.7',
32
- 'originally' => 'base_shipping_hidden_tax_amount'
33
- )
34
- )
35
- );
36
 
37
  /**
38
  * Render response
@@ -41,112 +29,160 @@ class SavvyCube_Connector_Model_Api_Order extends SavvyCube_Connector_Model_Api_
41
  */
42
  public function getMethod()
43
  {
44
- $sql = $this->getHelper()->getDbRead()->select()
45
- ->from(array('main_table' => $this->getHelper()->getTableName($this->mainTable)))
46
  ->joinLeft(
47
- array('group_table' => $this->getHelper()->getTableName('customer_group')),
48
- "group_table.customer_group_id = main_table.customer_group_id"
 
49
  )
50
- ->reset(Varien_Db_Select::COLUMNS)
51
- ->columns($this->columnsListForGet());
 
 
 
 
52
 
53
- return $this->getResult($sql, '`main_table`.updated_at');
 
 
 
 
54
  }
55
 
 
56
  /**
57
  * Return columns list for getMethod select
58
  *
59
  * @return string | array
60
  */
61
- protected function columnsListForGet()
62
  {
63
  return array_merge(
 
 
 
 
 
 
 
 
 
 
 
 
64
  $this->prepareColumns(
65
  array(
66
- 'entity_id',
67
- 'state',
68
- 'status',
69
- 'coupon_code',
70
- 'shipping_description',
71
- 'is_virtual',
72
- 'store_id',
73
- 'customer_id',
74
  'base_discount_amount',
75
  'base_discount_canceled',
76
  'base_discount_invoiced',
77
  'base_discount_refunded',
78
- 'base_grand_total',
 
 
 
 
 
 
 
 
 
 
 
79
  'base_shipping_amount',
80
  'base_shipping_canceled',
81
  'base_shipping_invoiced',
82
  'base_shipping_refunded',
83
- 'base_shipping_tax_amount',
84
- 'base_shipping_tax_refunded',
85
  'base_subtotal',
86
  'base_subtotal_canceled',
87
  'base_subtotal_invoiced',
88
  'base_subtotal_refunded',
89
- 'base_tax_amount',
90
- 'base_tax_canceled',
91
- 'base_tax_invoiced',
92
- 'base_tax_refunded',
93
- 'base_to_global_rate',
94
- 'base_to_order_rate',
95
  'base_total_canceled',
 
96
  'base_total_invoiced',
97
- 'base_total_invoiced_cost',
98
  'base_total_offline_refunded',
99
  'base_total_online_refunded',
100
  'base_total_paid',
101
- 'base_total_qty_ordered',
102
  'base_total_refunded',
103
- 'customer_is_guest',
104
- 'customer_note_notify',
 
 
 
 
 
 
 
105
  'billing_address_id',
106
- 'customer_group_id',
107
  'shipping_address_id',
108
- 'base_adjustment_negative',
109
- 'base_adjustment_positive',
110
- 'base_shipping_discount_amount',
111
- 'base_subtotal_incl_tax',
112
- 'base_total_due',
113
- 'weight',
114
- 'customer_dob',
115
  'increment_id',
116
- 'applied_rule_ids',
117
- 'base_currency_code',
 
 
 
118
  'customer_email',
119
  'customer_firstname',
 
 
 
120
  'customer_lastname',
121
  'customer_middlename',
122
  'customer_prefix',
123
  'customer_suffix',
124
  'customer_taxvat',
125
  'discount_description',
126
- 'global_currency_code',
127
- 'order_currency_code',
128
  'shipping_method',
 
 
129
  'store_name',
130
- 'customer_note',
131
  'created_at',
132
- 'updated_at',
133
- 'total_item_count',
134
- 'customer_gender',
135
- 'base_hidden_tax_amount',
136
- 'base_shipping_hidden_tax_amnt',
137
- 'base_hidden_tax_invoiced',
138
- 'base_hidden_tax_refunded',
139
- 'base_shipping_incl_tax',
140
- 'coupon_rule_name',
141
  ),
142
- 'main_table'
143
- ),
144
- $this->prepareColumns(
145
  array(
146
- 'customer_group_code'
147
- ),
148
- 'group_table'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  )
150
  );
151
  }
152
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Order extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_order';
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  /**
26
  * Render response
29
  */
30
  public function getMethod()
31
  {
32
+ $query = $this->generateQuery()
 
33
  ->joinLeft(
34
+ array('payment' => $this->getHelper()
35
+ ->getTableName('sales/order_payment')),
36
+ "main_table.entity_id = payment.parent_id"
37
  )
38
+ ->joinLeft(
39
+ array('st_label' => $this->getHelper()
40
+ ->getTableName('sales/order_status')),
41
+ "main_table.status = st_label.status"
42
+ );
43
+
44
 
45
+ $this->_data = $this->getResult(
46
+ $query->columns($this->columnsListForGet()),
47
+ '`main_table`.updated_at'
48
+ );
49
+ return true;
50
  }
51
 
52
+
53
  /**
54
  * Return columns list for getMethod select
55
  *
56
  * @return string | array
57
  */
58
+ public function columnsListForGet()
59
  {
60
  return array_merge(
61
+ $this->prepareColumns(
62
+ array('method'),
63
+ $this->getHelper()->getTableName('sales/order_payment'),
64
+ 'payment',
65
+ array('method' => 'payment_method')
66
+ ),
67
+ $this->prepareColumns(
68
+ array('label'),
69
+ $this->getHelper()->getTableName('sales/order_status'),
70
+ 'st_label',
71
+ array('label' => 'status_label')
72
+ ),
73
  $this->prepareColumns(
74
  array(
 
 
 
 
 
 
 
 
75
  'base_discount_amount',
76
  'base_discount_canceled',
77
  'base_discount_invoiced',
78
  'base_discount_refunded',
79
+ 'base_shipping_discount_amount',
80
+ 'base_hidden_tax_amount',
81
+ 'base_hidden_tax_invoiced',
82
+ 'base_hidden_tax_refunded',
83
+ 'base_shipping_hidden_tax_amnt',
84
+ 'base_shipping_hidden_tax_amount',
85
+ 'base_tax_amount',
86
+ 'base_tax_canceled',
87
+ 'base_tax_invoiced',
88
+ 'base_tax_refunded',
89
+ 'base_shipping_tax_amount',
90
+ 'base_shipping_tax_refunded',
91
  'base_shipping_amount',
92
  'base_shipping_canceled',
93
  'base_shipping_invoiced',
94
  'base_shipping_refunded',
 
 
95
  'base_subtotal',
96
  'base_subtotal_canceled',
97
  'base_subtotal_invoiced',
98
  'base_subtotal_refunded',
99
+ 'base_adjustment_negative',
100
+ 'base_adjustment_positive',
101
+ 'base_grand_total',
 
 
 
102
  'base_total_canceled',
103
+ 'base_total_due',
104
  'base_total_invoiced',
 
105
  'base_total_offline_refunded',
106
  'base_total_online_refunded',
107
  'base_total_paid',
 
108
  'base_total_refunded',
109
+ 'weight',
110
+ 'base_currency_code',
111
+ 'base_to_global_rate',
112
+ 'base_to_order_rate',
113
+ 'global_currency_code',
114
+ 'order_currency_code',
115
+ 'store_currency_code',
116
+ 'store_to_base_rate',
117
+ 'store_to_order_rate',
118
  'billing_address_id',
 
119
  'shipping_address_id',
120
+ 'entity_id',
 
 
 
 
 
 
121
  'increment_id',
122
+ 'store_id',
123
+ 'quote_id',
124
+ 'customer_id',
125
+ 'coupon_code',
126
+ 'coupon_rule_name',
127
  'customer_email',
128
  'customer_firstname',
129
+ 'customer_gender',
130
+ 'customer_group_id',
131
+ 'customer_is_guest',
132
  'customer_lastname',
133
  'customer_middlename',
134
  'customer_prefix',
135
  'customer_suffix',
136
  'customer_taxvat',
137
  'discount_description',
138
+ 'is_virtual',
139
+ 'shipping_description',
140
  'shipping_method',
141
+ 'state',
142
+ 'status',
143
  'store_name',
 
144
  'created_at',
145
+ 'updated_at'
 
 
 
 
 
 
 
 
146
  ),
147
+ $this->_mainTable,
148
+ 'main_table',
 
149
  array(
150
+ 'base_discount_amount' => 'discount_amount',
151
+ 'base_discount_canceled' => 'discount_canceled',
152
+ 'base_discount_invoiced' => 'discount_invoiced',
153
+ 'base_discount_refunded' => 'discount_refunded',
154
+ 'base_shipping_discount_amount' => 'shipping_discount_amount',
155
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
156
+ 'base_hidden_tax_invoiced' => 'hidden_tax_invoiced',
157
+ 'base_hidden_tax_refunded' => 'hidden_tax_refunded',
158
+ 'base_shipping_hidden_tax_amnt' => 'shipping_hidden_tax_amnt',
159
+ 'base_shipping_hidden_tax_amount' => 'shipping_hidden_tax_amnt',
160
+ 'base_tax_amount' => 'tax_amount',
161
+ 'base_tax_canceled' => 'tax_canceled',
162
+ 'base_tax_invoiced' => 'tax_invoiced',
163
+ 'base_tax_refunded' => 'tax_refunded',
164
+ 'base_shipping_tax_amount' => 'shipping_tax_amount',
165
+ 'base_shipping_tax_refunded' => 'shipping_tax_refunded',
166
+ 'base_shipping_amount' => 'shipping_amount',
167
+ 'base_shipping_canceled' => 'shipping_canceled',
168
+ 'base_shipping_invoiced' => 'shipping_invoiced',
169
+ 'base_shipping_refunded' => 'shipping_refunded',
170
+ 'base_subtotal' => 'subtotal',
171
+ 'base_subtotal_canceled' => 'subtotal_canceled',
172
+ 'base_subtotal_invoiced' => 'subtotal_invoiced',
173
+ 'base_subtotal_refunded' => 'subtotal_refunded',
174
+ 'base_adjustment_negative' => 'adjustment_negative',
175
+ 'base_adjustment_positive' => 'adjustment_positive',
176
+ 'base_grand_total' => 'grand_total',
177
+ 'base_total_canceled' => 'total_canceled',
178
+ 'base_total_due' => 'total_due',
179
+ 'base_total_invoiced' => 'total_invoiced',
180
+ 'base_total_offline_refunded' => 'total_offline_refunded',
181
+ 'base_total_online_refunded' => 'total_online_refunded',
182
+ 'base_total_paid' => 'total_paid',
183
+ 'base_total_refunded' => 'total_refunded'
184
+ )
185
  )
186
  );
187
  }
188
+ }
app/code/community/SavvyCube/Connector/Model/Api/{Address.php → Orderaddress.php} RENAMED
@@ -14,68 +14,49 @@
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
- class SavvyCube_Connector_Model_Api_Address extends SavvyCube_Connector_Model_Api_Abstract {
 
21
 
22
- protected $mainTable = 'sales_flat_order_address';
23
- /**
24
- * Render response on wCube/api/address get query
25
- *
26
- * @return array
27
- */
28
- public function getMethod()
29
- {
30
- $sql = $this->getHelper()->getDbRead()->select()
31
- ->from(array('main_table' => $this->getHelper()->getTableName($this->mainTable)))
32
- ->reset(Varien_Db_Select::COLUMNS)
33
- ->columns($this->columnsListForGet());
34
-
35
- $affectedOrders = $this->getAffectedOrders();
36
- if ($affectedOrders !== true && is_array($affectedOrders)) {
37
- if (count($affectedOrders)) {
38
- $sql->where("`main_table`.parent_id in (?)", $affectedOrders);
39
- } else {
40
- return array();
41
- }
42
- }
43
 
44
- return $this->getResult($sql);
45
- }
 
 
46
 
47
  /**
48
  * Return columns list for getMethod select
49
  *
50
  * @return string | array
51
  */
52
- protected function columnsListForGet()
53
  {
54
  return $this->prepareColumns(
55
  array(
56
  'entity_id',
57
  'parent_id',
58
- 'region_id',
59
- 'customer_id',
60
- 'fax',
61
- 'region',
62
- 'postcode',
63
- 'lastname',
64
- 'street',
65
  'city',
66
- 'email',
67
- 'telephone',
68
  'country_id',
 
 
69
  'firstname',
70
- 'address_type',
71
- 'prefix',
72
  'middlename',
 
 
 
 
73
  'suffix',
74
- 'company'
75
  ),
 
76
  'main_table'
77
  );
78
  }
79
 
80
 
81
- }
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
+ class SavvyCube_Connector_Model_Api_Orderaddress extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
 
24
+ protected $_mainTable = 'sales_flat_order_address';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ protected $_parentEntity = array(
27
+ 'table' => 'sales_flat_order',
28
+ 'parent_fk' => 'parent_id'
29
+ );
30
 
31
  /**
32
  * Return columns list for getMethod select
33
  *
34
  * @return string | array
35
  */
36
+ public function columnsListForGet()
37
  {
38
  return $this->prepareColumns(
39
  array(
40
  'entity_id',
41
  'parent_id',
42
+ 'address_type',
 
 
 
 
 
 
43
  'city',
 
 
44
  'country_id',
45
+ 'customer_id',
46
+ 'email',
47
  'firstname',
48
+ 'lastname',
 
49
  'middlename',
50
+ 'postcode',
51
+ 'prefix',
52
+ 'region',
53
+ 'region_id',
54
  'suffix',
 
55
  ),
56
+ $this->_mainTable,
57
  'main_table'
58
  );
59
  }
60
 
61
 
62
+ }
app/code/community/SavvyCube/Connector/Model/Api/Orderitem.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,98 +14,80 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Orderitem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_order_item';
24
 
25
- protected $versionColumns = array(
26
- 'tax_canceled' => array(
27
- 'since' => '1.6.0.0'
28
- ),
29
- 'hidden_tax_canceled' => array(
30
- 'since' => '1.6.0.0'
31
- ),
32
- 'base_tax_refunded' => array(
33
- 'since' => '1.6.0.5'
34
- ),
35
- 'base_discount_refunded' => array(
36
- 'since' => '1.6.0.5'
37
- ),
38
- 'base_weee_tax_applied_row_amnt' => array(
39
- 'renamed' => array(
40
- 'since' => '1.6.0.0',
41
- 'originally' => 'base_weee_tax_applied_row_amount'
42
- )
43
- )
44
- );
45
 
46
  /**
47
  * Return columns list for getMethod select
48
  *
49
  * @return string | array
50
  */
51
- protected function columnsListForGet()
52
  {
53
  return $this->prepareColumns(
54
  array(
55
- 'entity_id' => 'item_id',
56
- 'order_id',
57
- 'parent_item_id',
58
- 'created_at',
59
- 'updated_at',
60
- 'product_id',
61
- 'product_type',
62
- 'product_options',
63
- 'weight',
64
- 'is_virtual',
65
- 'sku',
66
- 'name',
67
- 'description',
68
- 'applied_rule_ids',
69
- 'additional_data',
70
- 'free_shipping',
71
- 'is_qty_decimal',
72
- 'no_discount',
73
- 'qty_backordered',
74
  'qty_canceled',
75
  'qty_invoiced',
76
  'qty_ordered',
77
  'qty_refunded',
 
78
  'qty_shipped',
79
- 'base_cost',
 
80
  'base_price',
 
81
  'base_original_price',
82
- 'tax_percent',
83
- 'base_tax_amount',
84
- 'base_tax_invoiced',
85
- 'discount_percent',
86
- 'base_discount_amount',
87
- 'base_discount_invoiced',
88
- 'base_amount_refunded',
89
- 'base_row_total',
90
- 'base_row_invoiced',
91
  'row_weight',
92
- 'base_tax_before_discount',
93
- 'base_price_incl_tax',
94
- 'base_row_total_incl_tax',
95
- 'base_hidden_tax_amount',
96
- 'base_hidden_tax_invoiced',
97
- 'base_hidden_tax_refunded',
98
- 'tax_canceled',
99
- 'hidden_tax_canceled',
100
- 'base_tax_refunded',
101
- 'base_discount_refunded',
102
- 'gift_message_id',
103
- 'gift_message_available',
104
- 'base_weee_tax_applied_amount',
105
- 'base_weee_tax_applied_row_amnt',
106
- 'base_weee_tax_disposition',
107
- 'base_weee_tax_row_disposition'
108
  ),
109
- 'main_table'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  );
111
  }
112
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Orderitem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_order_item';
24
 
25
+ protected $_order = 'main_table.item_id';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  /**
28
  * Return columns list for getMethod select
29
  *
30
  * @return string | array
31
  */
32
+ public function columnsListForGet()
33
  {
34
  return $this->prepareColumns(
35
  array(
36
+ 'base_discount_amount',
37
+ 'base_discount_invoiced',
38
+ 'base_discount_refunded',
39
+ 'discount_percent',
40
+ 'base_hidden_tax_amount',
41
+ 'base_hidden_tax_invoiced',
42
+ 'base_hidden_tax_refunded',
43
+ 'base_tax_amount',
44
+ 'base_tax_invoiced',
45
+ 'base_tax_refunded',
 
 
 
 
 
 
 
 
 
46
  'qty_canceled',
47
  'qty_invoiced',
48
  'qty_ordered',
49
  'qty_refunded',
50
+ 'qty_returned',
51
  'qty_shipped',
52
+ 'base_row_invoiced',
53
+ 'base_row_total',
54
  'base_price',
55
+ 'base_cost',
56
  'base_original_price',
57
+ 'weight',
 
 
 
 
 
 
 
 
58
  'row_weight',
59
+ 'created_at',
60
+ 'updated_at',
61
+ 'item_id',
62
+ 'order_id',
63
+ 'parent_item_id',
64
+ 'product_id',
65
+ 'quote_item_id',
66
+ 'description',
67
+ 'free_shipping',
68
+ 'is_virtual',
69
+ 'name',
70
+ 'product_type',
71
+ 'sku'
 
 
 
72
  ),
73
+ $this->_mainTable,
74
+ 'main_table',
75
+ array(
76
+ 'base_discount_amount' => 'discount_amount',
77
+ 'base_discount_invoiced' => 'discount_invoiced',
78
+ 'base_discount_refunded' => 'discount_refunded',
79
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
80
+ 'base_hidden_tax_invoiced' => 'hidden_tax_invoiced',
81
+ 'base_hidden_tax_refunded' => 'hidden_tax_refunded',
82
+ 'base_tax_amount' => 'tax_amount',
83
+ 'base_tax_invoiced' => 'tax_invoiced',
84
+ 'base_tax_refunded' => 'tax_refunded',
85
+ 'base_row_invoiced' => 'row_invoiced',
86
+ 'base_row_total' => 'row_total',
87
+ 'base_price' => 'price',
88
+ 'base_cost' => 'cost',
89
+ 'base_original_price' => 'original_price',
90
+ )
91
  );
92
  }
93
+ }
app/code/community/SavvyCube/Connector/Model/Api/Probe.php ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Probe extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+
24
+ protected $_categories;
25
+
26
+ /**
27
+ * Render response on savvycube/api/probe get query
28
+ *
29
+ * @return array
30
+ */
31
+ public function getMethod()
32
+ {
33
+ /** @var SavvyCube_Connector_Helper_Data $helper */
34
+ $helper = Mage::helper('wCube');
35
+ $currentVersion = $helper->getCurrentModuleVersion();
36
+ $currentTimezone = Mage::app()->getDefaultStoreView()->getConfig('general/locale/timezone');
37
+
38
+ $bottomOrderSql = $this->getHelper()->getDbRead()->select()
39
+ ->from(array('ent' => $this->getHelper()->getTableName('sales_flat_order')))
40
+ ->reset(Varien_Db_Select::COLUMNS)
41
+ ->columns('MIN(created_at) AS bottom_date');
42
+
43
+ $bottomQuoteSql = $this->getHelper()->getDbRead()->select()
44
+ ->from(array('ent' => $this->getHelper()->getTableName('sales_flat_quote')))
45
+ ->reset(Varien_Db_Select::COLUMNS)
46
+ ->columns('MIN(created_at) AS bottom_date');
47
+
48
+ $bottomCustomerSql = $this->getHelper()->getDbRead()->select()
49
+ ->from(array('ent' => $this->getHelper()->getTableName('customer_entity')))
50
+ ->reset(Varien_Db_Select::COLUMNS)
51
+ ->columns('MIN(created_at) AS bottom_date');
52
+
53
+ $bottomProductSql = $this->getHelper()->getDbRead()->select()
54
+ ->from(array('ent' => $this->getHelper()->getTableName('catalog_product_entity')))
55
+ ->reset(Varien_Db_Select::COLUMNS)
56
+ ->columns('MIN(created_at) AS bottom_date');
57
+
58
+ $start = microtime(true);
59
+ $bottomDate = $this->getHelper()->getDbRead()->fetchOne($bottomOrderSql);
60
+ $bottomQuoteDate = $this->getHelper()->getDbRead()->fetchOne($bottomQuoteSql);
61
+ $bottomCustomerDate = $this->getHelper()->getDbRead()->fetchOne($bottomCustomerSql);
62
+ $bottomProductDate = $this->getHelper()->getDbRead()->fetchOne($bottomProductSql);
63
+ $this->_queryTime += microtime(true) - $start;
64
+
65
+ $utcTimestamp = new DateTime(null, new DateTimeZone('UTC'));
66
+
67
+ $this->_data = array(
68
+ 'module_version' => $currentVersion,
69
+ 'magento_version' => Mage::getVersion(),
70
+ 'source_bottom' => min($bottomDate, $bottomQuoteDate, $bottomCustomerDate, $bottomProductDate),
71
+ 'utc_timestamp' => $utcTimestamp->format("Y-m-d H:i:s"),
72
+ 'timezone' => $currentTimezone,
73
+ 'stores' => $this->getStores(),
74
+ 'store_limits' => $this->getStoreLimits(),
75
+ 'limits' => $this->getLimits()
76
+ );
77
+ return true;
78
+ }
79
+
80
+ public function getStores()
81
+ {
82
+ $configValues = array(
83
+ 'base_url' => 'web/unsecure/base_url',
84
+ 'secure_base_url' => 'web/secure/base_url',
85
+ 'ga_property_id' => 'google/analytics/account',
86
+ 'ga_active' => 'google/analytics/active',
87
+ 'ga_ip_anonymization' => 'google/analytics/anonymization',
88
+ 'ga_type' => 'google/analytics/type'
89
+ );
90
+ $stores = Mage::app()->getStores(true, true);
91
+ foreach ($stores as $code => $store) {
92
+ $storeData = array();
93
+ $storeData['store_id'] = $store->getId();
94
+ $storeData['store_code'] = $code;
95
+ $storeData['store_name'] = $store->getName();
96
+ $storeData['is_default_store'] = (bool)$store->getId() ==
97
+ $store->getWebsite()->getDefaultStore()->getId();
98
+ $storeData['website_id'] = $store->getWebsite()->getId();
99
+ $storeData['website_code'] = $store->getWebsite()->getCode();
100
+ $storeData['website_name'] = $store->getWebsite()->getName();
101
+ $storeData['is_default_website'] = (bool)$store->getWebsite()
102
+ ->getIsDefault();
103
+ $storeData['root_category_id'] = $store->getRootCategoryId();
104
+ $storeData['root_category'] = $this->getCategoryName(
105
+ $store->getRootCategoryId()
106
+ );
107
+ foreach($configValues as $name => $path)
108
+ $storeData[$name] = Mage::getStoreConfig($path, $store);
109
+
110
+ $result[$code] = $storeData;
111
+ }
112
+
113
+ $this->_count = count($result);
114
+ return $result;
115
+ }
116
+
117
+ protected function getCategoryName($catId)
118
+ {
119
+ if (!isset($this->_categories[$catId])) {
120
+ $this->_categories[$catId] =
121
+ Mage::helper('wCube')->getFullCategoryPath($catId);
122
+ }
123
+
124
+ return $this->_categories[$catId];
125
+ }
126
+
127
+ public function getStoreLimits()
128
+ {
129
+ $result = array();
130
+ $stores = Mage::app()->getStores(true, true);
131
+ foreach ($stores as $code => $store) {
132
+ # category
133
+ $initialEnvironmentInfo = Mage::getSingleton('core/app_emulation')
134
+ ->startEnvironmentEmulation($store->getId());
135
+ $query = Mage::getModel('catalog/category')
136
+ ->getCollection()->getSelect()
137
+ ->reset(Varien_Db_Select::COLUMNS)
138
+ ->columns(array('max(updated_at) as max', 'min(updated_at) as min'));
139
+ $start = microtime(true);
140
+ $result[$store->getCode()]['category'] = $this->getHelper()->getDbRead()->fetchRow($query);
141
+ $this->_queryTime += microtime(true) - $start;
142
+ Mage::getSingleton('core/app_emulation')->stopEnvironmentEmulation($initialEnvironmentInfo);
143
+ # product
144
+ $prodCollection = Mage::getModel('catalog/product')
145
+ ->getCollection()->setStoreId($store->getId());
146
+ $db = Mage::getModel('core/resource')->getConnection('core_read');
147
+
148
+ $categoryTable = Mage::getSingleton('core/resource')
149
+ ->getTableName('catalog/category');
150
+ $categoryProdTable = Mage::getSingleton('core/resource')
151
+ ->getTableName('catalog/category_product');
152
+
153
+ $catSubquery = $db->select()
154
+ ->from(array('cat_prod' => $categoryProdTable))
155
+ ->joinLeft(
156
+ array('cat' => $categoryTable),
157
+ 'cat.entity_id = cat_prod.category_id'
158
+ )
159
+ ->reset(Varien_Db_Select::COLUMNS)
160
+ ->columns(
161
+ array(
162
+ 'cat_updated_at' => 'max(cat.updated_at)',
163
+ 'product_id' => 'cat_prod.product_id'
164
+ )
165
+ )
166
+ ->group('cat_prod.product_id');
167
+
168
+
169
+ $prodCollection->getSelect()
170
+ ->joinLeft(
171
+ array('cat_sum' => $catSubquery),
172
+ 'cat_sum.product_id = e.entity_id',
173
+ array()
174
+ );
175
+
176
+
177
+
178
+ if ($store->getWebsiteId() != 0) {
179
+ $website = $store->getWebsiteId();
180
+ $prodCollection->joinTable(
181
+ array('website' => 'catalog/product_website'),
182
+ 'product_id=entity_id',
183
+ array('website_id'),
184
+ "website_id = {$website}"
185
+ );
186
+ }
187
+
188
+ $query = $prodCollection->getSelect()
189
+ ->reset(Varien_Db_Select::COLUMNS)
190
+ ->columns(
191
+ array(
192
+ 'max(greatest(updated_at, cat_updated_at)) as max',
193
+ 'min(least(updated_at, cat_updated_at)) as min')
194
+ );
195
+
196
+ $start = microtime(true);
197
+ $result[$store->getCode()]['product'] = $this->getHelper()->getDbRead()->fetchRow($query);
198
+ $this->_queryTime += microtime(true) - $start;
199
+ }
200
+
201
+ return $result;
202
+ }
203
+
204
+ public function getLimits()
205
+ {
206
+ $result = array();
207
+ # customer
208
+ $result['customer'] = $this->getLimit('customer_entity', 'updated_at');
209
+ # order
210
+ $result['order'] = $this->getLimit('sales_flat_order', 'updated_at');
211
+ # quote
212
+ $result['quote'] = $this->getQuoteLimit();
213
+ # invoice
214
+ $result['invoice'] = $this->getLimit('sales_flat_invoice', 'updated_at');
215
+ #creditmemo
216
+ $result['refund'] = $this->getLimit('sales_flat_creditmemo', 'updated_at');
217
+ # shipment
218
+ $result['shipment'] = $this->getLimit('sales_flat_shipment', 'updated_at');
219
+ # url_rewrite
220
+ $result['rewrite'] = $this->getLimit('core_url_rewrite', 'url_rewrite_id');
221
+ # transaction
222
+ $result['transaction'] = $this->getLimit('sales_payment_transaction', 'created_at');
223
+ return $result;
224
+ }
225
+
226
+ public function getQuoteLimit()
227
+ {
228
+ $table = 'sales_flat_quote';
229
+ $column = 'main_table.updated_at';
230
+ $subQuery = $this->getHelper()->getDbRead()->select()
231
+ ->distinct()
232
+ ->from($this->getHelper()->getTableName('sales_flat_quote_item'))
233
+ ->reset(Varien_Db_Select::COLUMNS)
234
+ ->columns('quote_id');
235
+ $query = $this->getHelper()->getDbRead()->select()
236
+ ->from(array('main_table' => $this->getHelper()->getTableName($table)))
237
+ ->join(array('items' => $subQuery), 'main_table.entity_id = items.quote_id')
238
+ ->reset(Varien_Db_Select::COLUMNS)
239
+ ->columns(array("max({$column}) as max", "min({$column}) as min"));
240
+ $start = microtime(true);
241
+ $result = $this->getHelper()->getDbRead()->fetchRow($query);
242
+ $this->_queryTime += microtime(true) - $start;
243
+ return $result;
244
+ }
245
+
246
+ public function getLimit($table, $column)
247
+ {
248
+ $query = $this->getHelper()->getDbRead()->select()
249
+ ->from($this->getHelper()->getTableName($table))
250
+ ->reset(Varien_Db_Select::COLUMNS)
251
+ ->columns(array("max({$column}) as max", "min({$column}) as min"));
252
+ $start = microtime(true);
253
+ $result = $this->getHelper()->getDbRead()->fetchRow($query);
254
+ $this->_queryTime += microtime(true) - $start;
255
+ return $result;
256
+ }
257
+
258
+ public function init($params)
259
+ {
260
+ $this->_request = array();
261
+ return $this;
262
+ }
263
+
264
+
265
+ }
app/code/community/SavvyCube/Connector/Model/Api/Product.php ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Product extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+
24
+ protected $_categories;
25
+
26
+ public function getMethod()
27
+ {
28
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
29
+ $result = array();
30
+ $count = (int)$this->_request['count'];
31
+ $offset = (int)$this->_request['offset'];
32
+ $storeId = (int)$this->_request['store'];
33
+ $store = Mage::app()->getStore($storeId);
34
+
35
+ $productCollection = Mage::getModel('catalog/product')
36
+ ->getCollection()->setStoreId($storeId);
37
+ $productCollection->removeAttributeToSelect()
38
+ ->addAttributeToSelect('entity_id')
39
+ ->addAttributeToSelect('sku')
40
+ ->addAttributeToSelect('type_id')
41
+ ->addAttributeToSelect('name')
42
+ ->addAttributeToSelect('status')
43
+ ->addAttributeToSelect('url')
44
+ ->addAttributeToSelect('msrp')
45
+ ->addAttributeToSelect('visibility')
46
+ ->addAttributeToSelect('url_key')
47
+ ->joinField(
48
+ 'attribute_set_name',
49
+ Mage::getModel('eav/entity_attribute_set')
50
+ ->getResource()->getMainTable(),
51
+ 'attribute_set_name',
52
+ 'attribute_set_id=attribute_set_id'
53
+ );
54
+
55
+ $db = Mage::getModel('core/resource')->getConnection('core_read');
56
+
57
+ $categoryTable = Mage::getSingleton('core/resource')
58
+ ->getTableName('catalog/category');
59
+ $categoryProdTable = Mage::getSingleton('core/resource')
60
+ ->getTableName('catalog/category_product');
61
+
62
+ $catSubquery = $db->select()
63
+ ->from(array('cat_prod' => $categoryProdTable))
64
+ ->joinLeft(
65
+ array('cat' => $categoryTable),
66
+ 'cat.entity_id = cat_prod.category_id'
67
+ )
68
+ ->reset(Varien_Db_Select::COLUMNS)
69
+ ->columns(
70
+ array(
71
+ 'created_at' => 'max(cat.created_at)',
72
+ 'updated_at' => 'max(cat.updated_at)',
73
+ 'categories' => 'group_concat(cat_prod.category_id separator ",")',
74
+ 'product_id' => 'cat_prod.product_id'
75
+ )
76
+ )
77
+ ->group('cat_prod.product_id');
78
+
79
+
80
+ $productCollection->getSelect()
81
+ ->joinLeft(
82
+ array('cat_sum' => $catSubquery),
83
+ 'cat_sum.product_id = e.entity_id',
84
+ array(
85
+ 'max_cat_created_at' => 'cat_sum.created_at',
86
+ 'max_cat_updated_at' => 'cat_sum.updated_at',
87
+ 'categories' => 'cat_sum.categories'
88
+ )
89
+ );
90
+
91
+
92
+
93
+ if ($store->getWebsiteId() != 0) {
94
+ $website = $store->getWebsiteId();
95
+ $productCollection
96
+ ->joinTable(
97
+ array('website' => 'catalog/product_website'),
98
+ 'product_id=entity_id',
99
+ array('website_id'),
100
+ "website_id = {$website}"
101
+ );
102
+ }
103
+
104
+ $productCollection->getSelect()->limit($count, $offset);
105
+
106
+ $prodDate = 'e.updated_at';
107
+ $catDate = 'cat_sum.updated_at';
108
+
109
+ if (isset($this->_request['from'])) {
110
+ $productCollection->getSelect()
111
+ ->where(
112
+ "{$prodDate} >= ? OR {$catDate} >= ?",
113
+ $this->_request['from']
114
+ );
115
+ }
116
+
117
+ if (isset($this->_request['to'])) {
118
+ $productCollection->getSelect()
119
+ ->where(
120
+ "{$prodDate} <= ? OR {$catDate} <= ?",
121
+ $this->_request['to']
122
+ );
123
+ }
124
+
125
+ $start = microtime(true);
126
+ $products = $productCollection->getItems();
127
+ $this->_queryTime += microtime(true) - $start;
128
+
129
+ foreach ($products as $id => $product) {
130
+ $result[$id] = $this->processProduct(
131
+ $product,
132
+ $store
133
+ );
134
+ }
135
+
136
+ $this->_count = count($result);
137
+ $this->_data = $result;
138
+ return true;
139
+ }
140
+
141
+ protected function processProduct($product, $store)
142
+ {
143
+ $result['entity_id'] = $product->getEntityId();
144
+ $result['store_id'] = $store->getId();
145
+ $result['attribute_set'] = $product->getAttributeSetName();
146
+ $result['type_id'] = $product->getTypeId();
147
+ $result['sku'] = $product->getSku();
148
+ $result['name'] = $product->getName();
149
+ $result['status'] = $product->getAttributeText('status');
150
+ $result['visibility'] = $product->getAttributeText('visibility');
151
+ $result['url_key'] = $product->getUrlKey();
152
+ $result['msrp'] = $product->getMsrp();
153
+ $result['created_at'] = $product->getCreatedAt();
154
+ $result['updated_at'] = $product->getUpdatedAt();
155
+ $result['max_cat_created_at'] = $product->getMaxCatCreatedAt();
156
+ $result['max_cat_updated_at'] = $product->getMaxCatUpdatedAt();
157
+ if ($product->getCategories()) {
158
+ foreach(explode(',', $product->getCategories()) as $category)
159
+ $result['categories'][$category] = $this->getFullCategoryPath(
160
+ $category,
161
+ $store
162
+ );
163
+ } else {
164
+ $result['categories'] = array();
165
+ }
166
+
167
+ return $result;
168
+ }
169
+
170
+ protected function getFullCategoryPath($catId, $store)
171
+ {
172
+ $result = array();
173
+ if (!isset($this->_categories[$store->getId()])) {
174
+ $collection = Mage::getModel('catalog/category')->getCollection()
175
+ ->setStoreId($store->getId())
176
+ ->addAttributeToSelect('name');
177
+ $orFilter = array();
178
+ if ($store->getRootCategoryId() != 0) {
179
+ $rootCategory = $store->getRootCategoryId();
180
+ $orFilter[] = array('attribute' => 'path', 'like' => "1/{$rootCategory}");
181
+ $orFilter[] = array('attribute' => 'path', 'like' => "1/{$rootCategory}/%");
182
+ $orFilter[] = array('attribute' => 'parent_id', 'eq' => 0);
183
+ $collection->addAttributeToFilter($orFilter);
184
+ }
185
+
186
+ $this->_categories[$store->getId()] = $collection->getItems();
187
+ }
188
+
189
+ $categories = $this->_categories[$store->getId()];
190
+ if (isset($categories[$catId])) {
191
+ foreach ($categories[$catId]->getPathIds() as $id) {
192
+ if (isset($categories[$id])) {
193
+ $result[] = $categories[$id]->getName();
194
+ } else {
195
+ $result[] = 'Unknown';
196
+ }
197
+ }
198
+ }
199
+
200
+ if (isset($categories[$store->getRootCategoryId()])) {
201
+ $rootCategory = $categories[$store->getRootCategoryId()];
202
+ foreach ($rootCategory->getPathIds() as $id) {
203
+ if (isset($categories[$id])) {
204
+ $prefix = $categories[$id]->getName();
205
+ } else {
206
+ $prefix = 'Unknown';
207
+ }
208
+
209
+ if (!empty($result) && $result[0] == $prefix) {
210
+ array_shift($result);
211
+ } else {
212
+ break;
213
+ }
214
+ }
215
+ }
216
+
217
+ return implode('/', $result);
218
+ }
219
+
220
+ public function init($params)
221
+ {
222
+ parent::init($params);
223
+ $this->_request['store'] = array_key_exists('store', $params) ? $params['store'] : 0;
224
+ return $this;
225
+ }
226
+
227
+ }
app/code/community/SavvyCube/Connector/Model/Api/Quote.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Quote extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+ protected $_mainTable = 'sales_flat_quote';
24
+
25
+ /**
26
+ * Render response
27
+ *
28
+ * @return array
29
+ */
30
+ public function getMethod()
31
+ {
32
+ $this->_data = $this->getResult(
33
+ $this->generateQuery()
34
+ ->join(
35
+ array('with_items' => $this->generateSubQuery()),
36
+ "main_table.entity_id = with_items.quote_id"
37
+ )
38
+ ->reset(Varien_Db_Select::COLUMNS)
39
+ ->columns($this->columnsListForGet()),
40
+ 'main_table.updated_at'
41
+ );
42
+ return true;
43
+ }
44
+
45
+ public function generateSubQuery()
46
+ {
47
+ $query = $this->getHelper()->getDbRead()->select()
48
+ ->distinct()
49
+ ->from($this->getHelper()->getTableName('sales_flat_quote_item'))
50
+ ->reset(Varien_Db_Select::COLUMNS)
51
+ ->columns('quote_id');
52
+
53
+ return $query;
54
+ }
55
+
56
+ /**
57
+ * Return columns list for getMethod select
58
+ *
59
+ * @return string | array
60
+ */
61
+ public function columnsListForGet()
62
+ {
63
+ return $this->prepareColumns(
64
+ array(
65
+ 'base_subtotal',
66
+ 'base_grand_total',
67
+ 'base_currency_code',
68
+ 'base_to_global_rate',
69
+ 'base_to_quote_rate',
70
+ 'global_currency_code',
71
+ 'quote_currency_code',
72
+ 'store_currency_code',
73
+ 'store_to_base_rate',
74
+ 'store_to_quote_rate',
75
+ 'checkout_method',
76
+ 'coupon_code',
77
+ 'customer_email',
78
+ 'customer_firstname',
79
+ 'customer_id',
80
+ 'customer_group_id',
81
+ 'customer_is_guest',
82
+ 'customer_lastname',
83
+ 'customer_middlename',
84
+ 'customer_prefix',
85
+ 'customer_suffix',
86
+ 'customer_taxvat',
87
+ 'is_active',
88
+ 'is_changed',
89
+ 'is_virtual',
90
+ 'entity_id',
91
+ 'reserved_order_id',
92
+ 'store_id',
93
+ 'updated_at',
94
+ 'created_at'
95
+ ),
96
+ $this->_mainTable,
97
+ 'main_table',
98
+ array(
99
+ 'base_subtotal' => 'subtotal',
100
+ 'base_grand_total' => 'grand_total'
101
+ )
102
+ );
103
+ }
104
+ }
app/code/community/SavvyCube/Connector/Model/Api/Quoteaddress.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Quoteaddress extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+
24
+ protected $_mainTable = 'sales_flat_quote_address';
25
+
26
+ protected $_order = 'main_table.address_id';
27
+
28
+ /**
29
+ * Return columns list for getMethod select
30
+ *
31
+ * @return string | array
32
+ */
33
+ public function columnsListForGet()
34
+ {
35
+ return $this->prepareColumns(
36
+ array(
37
+ 'base_discount_amount',
38
+ 'base_shipping_discount_amount',
39
+ 'base_hidden_tax_amount',
40
+ 'base_shipping_hidden_tax_amnt',
41
+ 'base_shipping_hidden_tax_amount',
42
+ 'base_tax_amount',
43
+ 'base_shipping_tax_amount',
44
+ 'base_shipping_amount',
45
+ 'base_subtotal',
46
+ 'base_grand_total',
47
+ 'weight',
48
+ 'created_at',
49
+ 'updated_at',
50
+ 'customer_id',
51
+ 'quote_id',
52
+ 'address_id',
53
+ 'address_type',
54
+ 'city',
55
+ 'country_id',
56
+ 'discount_description',
57
+ 'email',
58
+ 'firstname',
59
+ 'free_shipping',
60
+ 'lastname',
61
+ 'middlename',
62
+ 'postcode',
63
+ 'prefix',
64
+ 'region',
65
+ 'region_id',
66
+ 'shipping_description',
67
+ 'shipping_method',
68
+ 'suffix'
69
+ ),
70
+ $this->_mainTable,
71
+ 'main_table',
72
+ array(
73
+ 'base_discount_amount' => 'discount_amount',
74
+ 'base_shipping_discount_amount' => 'shipping_discount_amount',
75
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
76
+ 'base_shipping_hidden_tax_amnt' => 'shipping_hidden_tax_amnt',
77
+ 'base_shipping_hidden_tax_amount' => 'shipping_hidden_tax_amnt',
78
+ 'base_tax_amount' => 'tax_amount',
79
+ 'base_shipping_tax_amount' => 'shipping_tax_amount',
80
+ 'base_shipping_amount' => 'shipping_amount',
81
+ 'base_subtotal' => 'subtotal',
82
+ 'base_grand_total' => 'grand_total',
83
+ )
84
+ );
85
+ }
86
+
87
+
88
+ }
app/code/community/SavvyCube/Connector/Model/Api/Quoteitem.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Quoteitem extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+ protected $_mainTable = 'sales_flat_quote_item';
24
+
25
+ protected $_order = 'main_table.item_id';
26
+
27
+ /**
28
+ * Return columns list for getMethod select
29
+ *
30
+ * @return string | array
31
+ */
32
+ public function columnsListForGet()
33
+ {
34
+ return $this->prepareColumns(
35
+ array(
36
+ 'base_discount_amount',
37
+ 'discount_percent',
38
+ 'base_hidden_tax_amount',
39
+ 'base_tax_amount',
40
+ 'qty',
41
+ 'quote_id',
42
+ 'base_row_total',
43
+ 'base_price',
44
+ 'base_cost',
45
+ 'weight',
46
+ 'row_weight',
47
+ 'created_at',
48
+ 'updated_at',
49
+ 'description',
50
+ 'free_shipping',
51
+ 'is_virtual',
52
+ 'name',
53
+ 'product_type',
54
+ 'sku',
55
+ 'item_id',
56
+ 'parent_item_id',
57
+ 'product_id'
58
+ ),
59
+ $this->_mainTable,
60
+ 'main_table',
61
+ array(
62
+ 'base_discount_amount' => 'discount_amount',
63
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
64
+ 'base_tax_amount' => 'tax_amount',
65
+ 'base_row_total' => 'row_total',
66
+ 'base_price' => 'price',
67
+ 'base_cost' => 'cost',
68
+ )
69
+ );
70
+ }
71
+ }
app/code/community/SavvyCube/Connector/Model/Api/Refund.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,69 +14,64 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Refund extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_creditmemo';
24
-
25
- protected $versionColumns = array(
26
- 'discount_description' => array(
27
- 'check_existence' => true
28
- ),
29
- 'base_shipping_hidden_tax_amnt' => array(
30
- 'renamed' => array(
31
- 'since' => '1.6.0.0',
32
- 'originally' => 'base_shipping_hidden_tax_amount'
33
- )
34
- )
35
- );
36
 
37
  /**
38
  * Return columns list for getMethod select
39
  *
40
  * @return string | array
41
  */
42
- protected function columnsListForGet()
43
  {
44
  return $this->prepareColumns(
45
  array(
46
- 'entity_id',
47
- 'base_shipping_tax_amount',
48
- 'store_to_order_rate',
49
  'base_discount_amount',
50
- 'base_to_order_rate',
51
- 'base_adjustment_negative',
52
- 'base_subtotal_incl_tax',
 
 
53
  'base_shipping_amount',
54
- 'store_to_base_rate',
55
- 'base_to_global_rate',
56
- 'base_adjustment',
57
  'base_subtotal',
58
- 'base_grand_total',
59
  'base_adjustment_positive',
60
- 'base_tax_amount',
61
- 'order_id',
62
- 'creditmemo_status',
63
- 'state',
64
- 'shipping_address_id',
65
- 'billing_address_id',
66
- 'invoice_id',
67
- 'store_currency_code',
68
- 'order_currency_code',
69
  'base_currency_code',
 
 
70
  'global_currency_code',
71
- 'transaction_id',
 
 
 
 
72
  'increment_id',
 
 
73
  'created_at',
74
  'updated_at',
75
- 'base_hidden_tax_amount',
76
- 'base_shipping_hidden_tax_amnt',
77
- 'base_shipping_incl_tax',
78
- 'discount_description',
79
  ),
80
- 'main_table'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  );
82
  }
83
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Refund extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_creditmemo';
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  /**
26
  * Return columns list for getMethod select
27
  *
28
  * @return string | array
29
  */
30
+ public function columnsListForGet()
31
  {
32
  return $this->prepareColumns(
33
  array(
 
 
 
34
  'base_discount_amount',
35
+ 'base_hidden_tax_amount',
36
+ 'base_shipping_hidden_tax_amnt',
37
+ 'base_shipping_hidden_tax_amount',
38
+ 'base_tax_amount',
39
+ 'base_shipping_tax_amount',
40
  'base_shipping_amount',
 
 
 
41
  'base_subtotal',
42
+ 'base_adjustment_negative',
43
  'base_adjustment_positive',
44
+ 'base_grand_total',
 
 
 
 
 
 
 
 
45
  'base_currency_code',
46
+ 'base_to_global_rate',
47
+ 'base_to_order_rate',
48
  'global_currency_code',
49
+ 'order_currency_code',
50
+ 'store_currency_code',
51
+ 'store_to_base_rate',
52
+ 'store_to_order_rate',
53
+ 'entity_id',
54
  'increment_id',
55
+ 'order_id',
56
+ 'transaction_id',
57
  'created_at',
58
  'updated_at',
 
 
 
 
59
  ),
60
+ $this->_mainTable,
61
+ 'main_table',
62
+ array(
63
+ 'base_discount_amount' => 'discount_amount',
64
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
65
+ 'base_shipping_hidden_tax_amnt' => 'shipping_hidden_tax_amnt',
66
+ 'base_shipping_hidden_tax_amount' => 'shipping_hidden_tax_amnt',
67
+ 'base_tax_amount' => 'tax_amount',
68
+ 'base_shipping_tax_amount' => 'shipping_tax_amount',
69
+ 'base_shipping_amount' => 'shipping_amount',
70
+ 'base_subtotal' => 'subtotal',
71
+ 'base_adjustment_negative' => 'adjustment_negative',
72
+ 'base_adjustment_positive' => 'adjustment_positive',
73
+ 'base_grand_total' => 'grand_total',
74
+ )
75
  );
76
  }
77
+ }
app/code/community/SavvyCube/Connector/Model/Api/Refunditem.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,56 +14,49 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Refunditem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_creditmemo_item';
24
 
25
- protected $parentEntity = array(
26
- 'model' => 'wCube/api_refund',
27
- 'parent_date' => 'updated_at',
28
  'parent_fk' => 'parent_id'
29
  );
30
 
31
- protected $versionColumns = array(
32
- 'base_weee_tax_applied_row_amnt' => array(
33
- 'renamed' => array(
34
- 'since' => '1.6.0.0',
35
- 'originally' => 'base_weee_tax_applied_row_amount'
36
- )
37
- )
38
- );
39
-
40
  /**
41
  * Return columns list for getMethod select
42
  *
43
  * @return string | array
44
  */
45
- protected function columnsListForGet()
46
  {
47
  return $this->prepareColumns(
48
  array(
49
- 'entity_id',
50
- 'parent_id',
51
- 'base_price',
52
- 'base_row_total',
53
  'base_discount_amount',
 
54
  'base_tax_amount',
55
- 'base_price_incl_tax',
56
  'qty',
 
 
57
  'base_cost',
58
- 'base_row_total_incl_tax',
59
- 'product_id',
60
  'order_item_id',
61
- 'base_hidden_tax_amount',
62
- 'base_weee_tax_disposition',
63
- 'base_weee_tax_row_disposition',
64
- 'base_weee_tax_applied_amount',
65
- 'base_weee_tax_applied_row_amnt',
66
  ),
67
- 'main_table'
 
 
 
 
 
 
 
 
 
68
  );
69
  }
70
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Refunditem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_creditmemo_item';
24
 
25
+ protected $_parentEntity = array(
26
+ 'table' => 'sales_flat_creditmemo',
 
27
  'parent_fk' => 'parent_id'
28
  );
29
 
 
 
 
 
 
 
 
 
 
30
  /**
31
  * Return columns list for getMethod select
32
  *
33
  * @return string | array
34
  */
35
+ public function columnsListForGet()
36
  {
37
  return $this->prepareColumns(
38
  array(
 
 
 
 
39
  'base_discount_amount',
40
+ 'base_hidden_tax_amount',
41
  'base_tax_amount',
 
42
  'qty',
43
+ 'base_price',
44
+ 'base_row_total',
45
  'base_cost',
46
+ 'entity_id',
 
47
  'order_item_id',
48
+ 'parent_id'
 
 
 
 
49
  ),
50
+ $this->_mainTable,
51
+ 'main_table',
52
+ array(
53
+ 'base_discount_amount' => 'discount_amount',
54
+ 'base_hidden_tax_amount' => 'hidden_tax_amount',
55
+ 'base_tax_amount' => 'tax_amount',
56
+ 'base_price' => 'price',
57
+ 'base_row_total' => 'row_total',
58
+ 'base_cost' => 'cost',
59
+ )
60
  );
61
  }
62
+ }
app/code/community/SavvyCube/Connector/Model/Api/Rewrite.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Api_Rewrite extends SavvyCube_Connector_Model_Api_Abstract
22
+ {
23
+ protected $_mainTable = 'core_url_rewrite';
24
+
25
+ protected $_order = 'main_table.url_rewrite_id';
26
+
27
+ /**
28
+ * Render response
29
+ *
30
+ * @return array
31
+ */
32
+ public function getMethod()
33
+ {
34
+ $this->_data = $this->getResult(
35
+ $this->generateQuery()->columns($this->columnsListForGet()),
36
+ '`main_table`.url_rewrite_id'
37
+ );
38
+
39
+ return true;
40
+ }
41
+ /**
42
+ * Return columns list for getMethod select
43
+ *
44
+ * @return string | array
45
+ */
46
+ public function columnsListForGet()
47
+ {
48
+ return $this->prepareColumns(
49
+ array(
50
+ 'url_rewrite_id',
51
+ 'store_id',
52
+ 'category_id',
53
+ 'id_path',
54
+ 'request_path',
55
+ 'target_path',
56
+ 'product_id'
57
+ ),
58
+ $this->_mainTable,
59
+ 'main_table'
60
+ );
61
+ }
62
+ }
app/code/community/SavvyCube/Connector/Model/Api/Shipment.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,37 +14,35 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Shipment extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_shipment';
24
 
25
  /**
26
  * Return columns list for getMethod select
27
  *
28
  * @return string | array
29
  */
30
- protected function columnsListForGet()
31
  {
32
  return $this->prepareColumns(
33
  array(
34
- 'entity_id',
35
- 'store_id',
36
- 'total_weight',
37
  'total_qty',
38
- 'order_id',
 
39
  'customer_id',
40
- 'shipping_address_id',
41
- 'billing_address_id',
42
- 'shipment_status',
43
  'increment_id',
 
44
  'created_at',
45
  'updated_at',
46
- 'shipping_label',
47
  ),
 
48
  'main_table'
49
  );
50
  }
51
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Shipment extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_shipment';
24
 
25
  /**
26
  * Return columns list for getMethod select
27
  *
28
  * @return string | array
29
  */
30
+ public function columnsListForGet()
31
  {
32
  return $this->prepareColumns(
33
  array(
 
 
 
34
  'total_qty',
35
+ 'total_weight',
36
+ 'store_id',
37
  'customer_id',
38
+ 'entity_id',
 
 
39
  'increment_id',
40
+ 'order_id',
41
  'created_at',
42
  'updated_at',
 
43
  ),
44
+ $this->_mainTable,
45
  'main_table'
46
  );
47
  }
48
+ }
app/code/community/SavvyCube/Connector/Model/Api/Shipmentitem.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,16 +14,16 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Shipmentitem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_flat_shipment_item';
24
 
25
- protected $parentEntity = array(
26
- 'model' => 'wCube/api_shipment',
27
- 'parent_date' => 'updated_at',
28
  'parent_fk' => 'parent_id'
29
  );
30
 
@@ -33,20 +32,19 @@ class SavvyCube_Connector_Model_Api_Shipmentitem extends SavvyCube_Connector_Mod
33
  *
34
  * @return string | array
35
  */
36
- protected function columnsListForGet()
37
  {
38
  return $this->prepareColumns(
39
  array(
40
  'entity_id',
 
41
  'parent_id',
42
- 'row_total',
43
- 'price',
44
- 'weight',
45
- 'qty',
46
  'product_id',
47
- 'order_item_id',
 
48
  ),
 
49
  'main_table'
50
  );
51
  }
52
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Shipmentitem extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_flat_shipment_item';
24
 
25
+ protected $_parentEntity = array(
26
+ 'table' => 'sales_flat_shipment',
 
27
  'parent_fk' => 'parent_id'
28
  );
29
 
32
  *
33
  * @return string | array
34
  */
35
+ public function columnsListForGet()
36
  {
37
  return $this->prepareColumns(
38
  array(
39
  'entity_id',
40
+ 'order_item_id',
41
  'parent_id',
 
 
 
 
42
  'product_id',
43
+ 'qty',
44
+ 'weight',
45
  ),
46
+ $this->_mainTable,
47
  'main_table'
48
  );
49
  }
50
+ }
app/code/community/SavvyCube/Connector/Model/Api/Transaction.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,13 +14,15 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Transaction extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
- protected $mainTable = 'sales_payment_transaction';
24
 
 
25
 
26
  /**
27
  * Render response
@@ -31,7 +32,7 @@ class SavvyCube_Connector_Model_Api_Transaction extends SavvyCube_Connector_Mode
31
  public function getMethod()
32
  {
33
  $sql = $this->getHelper()->getDbRead()->select()
34
- ->from(array('main_table' => $this->getHelper()->getTableName($this->mainTable)))
35
  ->joinLeft(
36
  array('payment_table' => $this->getHelper()->getTableName('sales_flat_order_payment')),
37
  "main_table.payment_id = payment_table.entity_id"
@@ -39,7 +40,8 @@ class SavvyCube_Connector_Model_Api_Transaction extends SavvyCube_Connector_Mode
39
  ->reset(Varien_Db_Select::COLUMNS)
40
  ->columns($this->columnsListForGet());
41
 
42
- return $this->getResult($sql, '`main_table`.created_at');
 
43
  }
44
 
45
  /**
@@ -47,37 +49,34 @@ class SavvyCube_Connector_Model_Api_Transaction extends SavvyCube_Connector_Mode
47
  *
48
  * @return string | array
49
  */
50
- protected function columnsListForGet()
51
  {
52
  return array_merge(
53
  $this->prepareColumns(
54
  array(
55
- 'base_shipping_captured',
56
- 'base_amount_paid',
57
- 'base_amount_authorized',
58
- 'base_amount_paid_online',
59
- 'base_amount_refunded_online',
60
- 'base_shipping_amount',
61
- 'base_amount_ordered',
62
- 'base_shipping_refunded',
63
- 'base_amount_refunded',
64
- 'base_amount_canceled',
65
  'method',
66
  'last_trans_id'
67
  ),
68
- 'payment_table'
 
 
 
 
69
  ),
70
  $this->prepareColumns(
71
  array(
72
- 'entity_id' => 'transaction_id',
73
- 'order_id',
74
  'txn_id',
 
75
  'txn_type',
76
  'is_closed',
77
  'created_at'
78
  ),
 
79
  'main_table'
80
  )
81
  );
82
  }
83
- }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_Model_Api_Transaction extends SavvyCube_Connector_Model_Api_Abstract
22
  {
23
+ protected $_mainTable = 'sales_payment_transaction';
24
 
25
+ protected $_order = 'payment_table.entity_id';
26
 
27
  /**
28
  * Render response
32
  public function getMethod()
33
  {
34
  $sql = $this->getHelper()->getDbRead()->select()
35
+ ->from(array('main_table' => $this->getHelper()->getTableName($this->_mainTable)))
36
  ->joinLeft(
37
  array('payment_table' => $this->getHelper()->getTableName('sales_flat_order_payment')),
38
  "main_table.payment_id = payment_table.entity_id"
40
  ->reset(Varien_Db_Select::COLUMNS)
41
  ->columns($this->columnsListForGet());
42
 
43
+ $this->_data = $this->getResult($sql, '`main_table`.created_at');
44
+ return true;
45
  }
46
 
47
  /**
49
  *
50
  * @return string | array
51
  */
52
+ public function columnsListForGet()
53
  {
54
  return array_merge(
55
  $this->prepareColumns(
56
  array(
57
+ 'parent_id',
58
+ 'entity_id',
 
 
 
 
 
 
 
 
59
  'method',
60
  'last_trans_id'
61
  ),
62
+ 'sales_flat_order_payment',
63
+ 'payment_table',
64
+ array(
65
+ 'parent_id' => 'order_id'
66
+ )
67
  ),
68
  $this->prepareColumns(
69
  array(
70
+ 'transaction_id',
 
71
  'txn_id',
72
+ 'parrent_txn_id',
73
  'txn_type',
74
  'is_closed',
75
  'created_at'
76
  ),
77
+ $this->_mainTable,
78
  'main_table'
79
  )
80
  );
81
  }
82
+ }
app/code/community/SavvyCube/Connector/Model/Api/Version.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Magento
5
- *
6
- * NOTICE OF LICENSE
7
- *
8
- * This source file is subject to the Open Software License (OSL 3.0)
9
- * that is bundled with this package in the file LICENSE.txt.
10
- * It is also available through the world-wide-web at this URL:
11
- * http://opensource.org/licenses/osl-3.0.php
12
- * If you did not receive a copy of the license and are unable to
13
- * obtain it through the world-wide-web, please send an email
14
- * to license@savvycube.com so we can send you a copy immediately.
15
- *
16
- * @category SavvyCube
17
- * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
19
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
- */
21
- class SavvyCube_Connector_Model_Api_Version extends SavvyCube_Connector_Model_Api_Abstract
22
- {
23
-
24
-
25
- /**
26
- * Render response on wCube/api/version get query
27
- *
28
- * @return array
29
- */
30
- public function getMethod()
31
- {
32
- /** @var SavvyCube_Connector_Helper_Data $helper */
33
- $helper = Mage::helper('wCube');
34
- $currentVersion = $helper->getCurrentModuleVersion();
35
- $currentTimezone = Mage::app()->getDefaultStoreView()->getConfig('general/locale/timezone');
36
-
37
- if (array_key_exists('version', $this->request)
38
- && $this->request['version'] != $currentVersion
39
- ) {
40
- $helper->setDesiredVersion($this->request['version']);
41
- }
42
-
43
- $bottomDateSql = $this->getHelper()->getDbRead()->select()
44
- ->from(array('order' => $this->getHelper()->getTableName('sales_flat_order')))
45
- ->reset(Varien_Db_Select::COLUMNS)
46
- ->columns('MIN(created_at) AS bottom_date');
47
-
48
- $bottomDate = $this->getHelper()->getDbRead()->fetchOne($bottomDateSql);
49
-
50
- return array(
51
- 'module_version' => $currentVersion,
52
- 'magento_version' => Mage::getVersion(),
53
- 'source_bottom' => $bottomDate,
54
- 'timezone' => $currentTimezone
55
- );
56
- }
57
-
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/SavvyCube/Connector/{controllers/Adminhtml/IndexController.php → Model/Baseurl.php} RENAMED
@@ -14,25 +14,26 @@
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
- class SavvyCube_Connector_Adminhtml_IndexController extends Mage_Adminhtml_Controller_Action
21
  {
22
  /**
23
- * Authorization Helper
24
  *
25
- * @return SavvyCube_Connector_Helper_Authorization
26
  */
27
- protected function getAuthHelper()
28
  {
29
- return Mage::helper('wCube/authorization');
 
 
 
 
 
 
 
 
30
  }
31
-
32
- public function indexAction()
33
- {
34
- $this->getAuthHelper()->initConsumerKey();
35
- header("Location: ".$this->getAuthHelper()->getActivateUrl());
36
- die();
37
- }
38
- }
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
+ class SavvyCube_Connector_Model_Baseurl extends Mage_Core_Model_Config_Data
22
  {
23
  /**
24
+ * Decrypt value after loading
25
  *
 
26
  */
27
+ protected function _afterLoad()
28
  {
29
+ if (empty($this->getValue())) {
30
+ $baseUrl = Mage::app()->getDefaultStoreView()->getBaseUrl();
31
+ $this->setValue($baseUrl);
32
+ Mage::getConfig()->saveConfig(
33
+ 'w_cube/settings/base_url', $baseUrl, 'default', 0
34
+ );
35
+ Mage::getConfig()->cleanCache();
36
+ Mage::app()->reinitStores();
37
+ }
38
  }
39
+ }
 
 
 
 
 
 
 
app/code/community/SavvyCube/Connector/Model/Nonce.php DELETED
@@ -1,155 +0,0 @@
1
- <?php
2
- /**
3
- * Magento
4
- *
5
- * NOTICE OF LICENSE
6
- *
7
- * This source file is subject to the Open Software License (OSL 3.0)
8
- * that is bundled with this package in the file LICENSE.txt.
9
- * It is also available through the world-wide-web at this URL:
10
- * http://opensource.org/licenses/osl-3.0.php
11
- * If you did not receive a copy of the license and are unable to
12
- * obtain it through the world-wide-web, please send an email
13
- * to license@savvycube.com so we can send you a copy immediately.
14
- *
15
- * @category SavvyCube
16
- * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
18
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
- */
20
-
21
- /**
22
- * Class SavvyCube_Connector_Model_Nonce
23
- * @method Mage_Core_Model_Resource getResource()
24
- * @method SavvyCube_Connector_Model_Nonce setResource(Mage_Core_Model_Resource $model)
25
- * @method string getTable()
26
- * @method SavvyCube_Connector_Model_Nonce setTable(string $tableName)
27
- * @method string getCurrentTimestamp()
28
- * @method SavvyCube_Connector_Model_Nonce setCurrentTimestamp(string)
29
- *
30
- */
31
- class SavvyCube_Connector_Model_Nonce extends Varien_Object
32
- {
33
- /**
34
- * @return SavvyCube_Connector_Helper_Authorization
35
- */
36
- private function getAuthHelper()
37
- {
38
- return Mage::helper('wCube/authorization');
39
- }
40
-
41
- protected function _construct()
42
- {
43
- $this->setResource(Mage::getSingleton('core/resource'));
44
- $this->setTable($this->getResource()->getTableName('wCube/nonce'));
45
- $this->setCurrentTimestamp(gmdate('U'));
46
- parent::_construct();
47
- }
48
-
49
- /**
50
- * remove old nonce from DB table
51
- *
52
- * @return Zend_Db_Pdo_Statement
53
- */
54
- private function cleanTable()
55
- {
56
- $lifeTime = $this->getAuthHelper()->getNonceLifetime(true);
57
- $query = "DELETE FROM `{$this->getTable()}` WHERE `created` <= " . ($this->getCurrentTimestamp() - $lifeTime);
58
- return $this->write($query);
59
- }
60
-
61
- /**
62
- * store nonce
63
- *
64
- * @param string $nonce nonce value
65
- *
66
- * @return Zend_Db_Pdo_Statement
67
- */
68
- private function storeNonce($nonce)
69
- {
70
- $query = "INSERT INTO `{$this->getTable()}` VALUES (:nonce, :current_timestamp)";
71
- return $this->write(
72
- $query,
73
- array(
74
- 'nonce' => $nonce,
75
- 'current_timestamp' => $this->getCurrentTimestamp()
76
- )
77
- );
78
- }
79
-
80
- /**
81
- * check if nonce already stored in last lifeTime seconds
82
- *
83
- * @param string $nonce nonce value
84
- * @param string $created nonce creation datetime in GMT format
85
- *
86
- * @return bool
87
- */
88
- private function findDoubling($nonce, $created)
89
- {
90
- $date = new DateTime($created);
91
- $timeDiff = $this->getCurrentTimestamp() - $date->format('U');
92
- if (!($timeDiff > $this->getAuthHelper()->getNonceLifetime(true))) {
93
- $query = "SELECT * FROM `{$this->getTable()}` "
94
- . " WHERE `nonce`=:nonce AND (:current_timestamp - `created`) < :lifetime";
95
- $bind = array(
96
- 'nonce' => $nonce,
97
- 'current_timestamp' => $this->getCurrentTimestamp(),
98
- 'lifetime' => $this->getAuthHelper()->getNonceLifetime(true),
99
- );
100
- $result = $this->read($query, $bind);
101
- if (!count($result)) {
102
- return false;
103
- }
104
- }
105
- return true;
106
- }
107
-
108
- /**
109
- * write date to DB
110
- *
111
- * @param string $query sql statement
112
- * @param array $bind
113
- *
114
- * @return Zend_Db_Pdo_Statement
115
- */
116
- private function write($query, $bind = array())
117
- {
118
- $connection = $this->getResource()->getConnection('core_write');
119
- return $connection->query($query, $bind);
120
- }
121
-
122
- /**
123
- * read data from DB
124
- *
125
- * @param string $query sql statement
126
- * @param array $bind
127
- *
128
- * @return array
129
- */
130
- private function read($query, $bind = array())
131
- {
132
- $connection = $this->getResource()->getConnection('core_read');
133
- return $connection->fetchAll($query, $bind);
134
- }
135
-
136
- /**
137
- * check nonce, store it and clean old nonce
138
- *
139
- * @param string $nonce nonce value
140
- * @param string $created nonce creation datetime in GMT format
141
- *
142
- * @return bool
143
- */
144
- public function checkNonce($nonce, $created)
145
- {
146
- if (!$this->findDoubling($nonce, $created)) {
147
- $this->storeNonce($nonce);
148
- $this->cleanTable();
149
- return true;
150
- }
151
- return false;
152
- }
153
-
154
-
155
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/SavvyCube/Connector/Model/Resource/Main.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_Model_Resource_Main extends Mage_Core_Model_Resource
22
+ {
23
+ const NONCE_TTL = 900; # 15 min
24
+
25
+ const SESSION_TTL = 600; # 10 min
26
+
27
+ public function checkNonce($nonce)
28
+ {
29
+ $nonce = (int)$nonce;
30
+ $nonceTable = $this->getTableName('wCube/nonce');
31
+ $select = $this->getConnection('core_read')->select();
32
+ $select->from($nonceTable, 'nonce')
33
+ ->where('nonce = ?', $nonce)
34
+ ->where('UNIX_TIMESTAMP() - UNIX_TIMESTAMP(created_at) < ?', self::NONCE_TTL);
35
+ $duplicate = $this->getConnection('core_read')->fetchOne($select);
36
+ if (!$duplicate) {
37
+ $this->getConnection('core_write')
38
+ ->insert($nonceTable, array('nonce' => $nonce));
39
+ return true;
40
+ }
41
+
42
+ return false;
43
+ }
44
+
45
+ public function cleanNonce()
46
+ {
47
+ $nonceTable = $this->getTableName('wCube/nonce');
48
+ $this->getConnection('core_write')
49
+ ->delete(
50
+ $nonceTable,
51
+ array('UNIX_TIMESTAMP() - UNIX_TIMESTAMP(created_at) > ?' => self::NONCE_TTL)
52
+ );
53
+ }
54
+
55
+ public function cleanSession()
56
+ {
57
+ $sessionTable = $this->getTableName('wCube/session');
58
+ $this->getConnection('core_write')
59
+ ->delete(
60
+ $sessionTable,
61
+ array('UNIX_TIMESTAMP() - UNIX_TIMESTAMP(created_at) > ?' => self::SESSION_TTL)
62
+ );
63
+ }
64
+
65
+ public function createSession($key)
66
+ {
67
+ $session = uniqid('session_');
68
+ $sessionTable = $this->getTableName('wCube/session');
69
+ $this->getConnection('core_write')
70
+ ->insert($sessionTable, array('session' => $session, 'key' => $key));
71
+ return $session;
72
+ }
73
+
74
+ public function getKeyBySession($session)
75
+ {
76
+ $sessionTable = $this->getTableName('wCube/session');
77
+ $select = $this->getConnection('core_read')->select();
78
+ $select->from($sessionTable, 'key')
79
+ ->where('session = ?', $session)
80
+ ->where('UNIX_TIMESTAMP() - UNIX_TIMESTAMP(created_at) < ?', self::SESSION_TTL);
81
+ $key = $this->getConnection('core_read')->fetchOne($select);
82
+ if ($key)
83
+ return $key;
84
+ return False;
85
+ }
86
+
87
+ }
app/code/community/SavvyCube/Connector/cert/x509.crt DELETED
@@ -1,25 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEHzCCAwegAwIBAgIBADANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx
3
- FzAVBgNVBAgMDk1pbm5lc290YSAoTU4pMRQwEgYDVQQHDAtNaW5uZWFwb2xpczEY
4
- MBYGA1UECgwPV2VidGV4IFNvZnR3YXJlMRgwFgYDVQQLDA9XZWJ0ZXggU29mdHdh
5
- cmUxDzANBgNVBAMMBldlYnRleDEmMCQGCSqGSIb3DQEJARYXaW5mb0B3ZWJ0ZXhz
6
- b2Z0d2FyZS5jb20wHhcNMTQwMTEwMTQxNTQ4WhcNMTUwMTEwMTQxNTQ4WjCBqTEL
7
- MAkGA1UEBhMCVVMxFzAVBgNVBAgMDk1pbm5lc290YSAoTU4pMRQwEgYDVQQHDAtN
8
- aW5uZWFwb2xpczEYMBYGA1UECgwPV2VidGV4IFNvZnR3YXJlMRgwFgYDVQQLDA9X
9
- ZWJ0ZXggU29mdHdhcmUxDzANBgNVBAMMBldlYnRleDEmMCQGCSqGSIb3DQEJARYX
10
- aW5mb0B3ZWJ0ZXhzb2Z0d2FyZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
11
- ggEKAoIBAQCyXV1lWfPn2z9y1YWDXPWQBFYo5P33Qr1yXYbgTuE/svtjnXaSMaeO
12
- diEEmceJ+0RFKqHU95NVdVxsfL+YJYiewxvB+QAhW4SngEFW3fCxNXLbd4wFZH5e
13
- 8EjyqqZP2Qen21joOF9X/gXZ0NvUmNhh1uZUJN6inlt8ZuKQPBGWsXRKg2KkwJcS
14
- JJ/4kYIU3xHwaiLnlusrqTjtidUAVSdGY0HKbW0oLosPKRmQH1YyO2YodgcMIvuK
15
- OtbV3du6lb3EIWPsMOal6DpLqzem0IB+C4HFfHZzAf31Dd9cztY4YQIG9yoFOjD6
16
- iId6C957JGbwvTQaQg2mNyGtdWLldVUvAgMBAAGjUDBOMB0GA1UdDgQWBBRaofNM
17
- 2OEE/h6vVXXIktwUaoX9ATAfBgNVHSMEGDAWgBRaofNM2OEE/h6vVXXIktwUaoX9
18
- ATAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQCFTz1pLqC9VSuQxoXB
19
- n5q1mPzeD237H0Aj8wbZhkNePLMh6MDAkloURkCjpwD8ZEFmwJVnM6ebStyCkP8f
20
- xHpTzRJGWcfx0pn5QTrzrNtfBmolp3q4Iy9ckUVSz/W3BVLGpXlQZPHHbUu9p/uY
21
- ldsg3AAFPVN+H5V2qSPUSdJAuVhoo3/eZt5XSmAK6fqgDNVNmmqO0+rVKgSghCmw
22
- KjYHVY6SOG0dThkK4G9r+30TcylDVjGMCX1katuH6XdmmxdfYZeWxbgnPj2t2pqI
23
- s1rwEFtUAKZD3CzyE3pKZ+sUfwlgvxe1HDts262ukFPLIhqGHCOGoWXhb3J/7I3X
24
- SlbT
25
- -----END CERTIFICATE-----
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/SavvyCube/Connector/controllers/ApiController.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Magento
5
  *
@@ -15,215 +14,102 @@
15
  *
16
  * @category SavvyCube
17
  * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_ApiController extends Mage_Core_Controller_Front_Action
22
  {
23
- private function _authorize()
24
- {
25
- if (!$this->getAuthHelper()->checkRequest()) {
26
- Mage::app()->getResponse()
27
- ->setHeader('HTTP/1.1', '401 Unauthorized')
28
- ->setBody('<h1>401 Unauthorized</h1>')
29
- ->sendResponse();
30
- exit;
31
- }
32
- }
33
 
34
- private function formatResponse($data, $encrypt)
35
- {
36
- if ($encrypt) {
37
- Mage::app()->getResponse()->setHeader('Content-Type', 'text/plain');
38
- Mage::app()->getResponse()->setHeader('Content-Encoding', 'gzip');
39
- Mage::app()->getResponse()->setBody(
40
- $this->encrypt(Mage::helper('core')->jsonEncode($data))
41
- );
42
- } else {
43
- Mage::app()->getResponse()->setHeader('Content-Type', 'application/json');
44
- Mage::app()->getResponse()->setBody(
45
- Mage::helper('core')->jsonEncode($data)
46
- );
47
- }
48
- }
49
-
50
- private function encrypt($data)
51
- {
52
- $key = $this->getAuthHelper()->getCurrentKey('e');
53
-
54
- return rtrim(
55
- base64_encode(
56
- mcrypt_encrypt(
57
- MCRYPT_RIJNDAEL_128,
58
- $key,
59
- gzencode($data),
60
- MCRYPT_MODE_ECB,
61
- mcrypt_create_iv(
62
- mcrypt_get_iv_size(
63
- MCRYPT_RIJNDAEL_128,
64
- MCRYPT_MODE_ECB
65
- ),
66
- MCRYPT_DEV_URANDOM
67
- )
68
- )
69
- ),
70
- "\0"
71
- );
72
 
73
- }
74
-
75
- /**
76
- * Authorization Helper
77
- *
78
- * @return SavvyCube_Connector_Helper_Authorization
79
- */
80
  protected function getAuthHelper()
81
  {
82
  return Mage::helper('wCube/authorization');
83
  }
84
 
85
- public function dispatch($action)
86
  {
87
- $this->_authorize();
88
- try {
89
- $apiResource = Mage::getModel('wCube/api_' . $action);
90
- $method = strtolower($this->getRequest()->getMethod()) . "Method";
91
- try {
92
- $parameters = $this->_getParameters();
93
- } catch (Exception $e) {
94
- Mage::app()->getResponse()
95
- ->setHeader('HTTP/1.1', '404 Not Found')
96
- ->setBody($e->getMessage())
97
- ->sendResponse();
98
- exit;
99
- }
100
-
101
- if (!$apiResource) {
102
- Mage::app()->getResponse()
103
- ->setHeader('HTTP/1.1', '404 Not Found')
104
- ->setBody('<h1>404: Api resource not found</h1>')
105
- ->sendResponse();
106
- exit;
107
  } else {
108
- if (($this->_isEncryptionRequired($action, $this->getRequest()->getMethod())
109
- && !$this->getAuthHelper()->getCurrentKey('e'))
110
- ) {
111
- Mage::app()->getResponse()
112
- ->setHeader('HTTP/1.1', '401 Unauthorized')
113
- ->setBody('no encryption key')
114
- ->sendResponse();
115
- exit;
116
- } elseif (!is_callable(array($apiResource, $method))) {
117
- Mage::app()->getResponse()
118
- ->setHeader('HTTP/1.1', '404 Not Found')
119
- ->setBody('<h1>404: method is not supported for this Api resource</h1>')
120
- ->sendResponse();
121
- exit;
122
- }
123
- }
124
-
125
- Varien_Profiler::start(self::PROFILER_KEY . '::predispatch');
126
- $this->preDispatch();
127
- Varien_Profiler::stop(self::PROFILER_KEY . '::predispatch');
128
-
129
- if ($this->getRequest()->isDispatched()) {
130
- /**
131
- * preDispatch() didn't change the action, so we can continue
132
- */
133
- if (!$this->getFlag('', self::FLAG_NO_DISPATCH)) {
134
- $_profilerKey = self::PROFILER_KEY . '::' . $this->getFullActionName();
135
 
136
- Varien_Profiler::start($_profilerKey);
137
- $response = $apiResource->init($parameters)->$method();
138
- $this->formatResponse($response, $this->_isEncryptionRequired($action, $this->getRequest()->getMethod()));
139
- Varien_Profiler::stop($_profilerKey);
140
 
141
- Varien_Profiler::start(self::PROFILER_KEY . '::postdispatch');
142
- $this->postDispatch();
143
- Varien_Profiler::stop(self::PROFILER_KEY . '::postdispatch');
 
 
 
 
 
144
  }
145
  }
146
- } catch (Mage_Core_Controller_Varien_Exception $e) {
147
- // set prepared flags
148
- foreach ($e->getResultFlags() as $flagData) {
149
- list($action, $flag, $value) = $flagData;
150
- $this->setFlag($action, $flag, $value);
151
- }
152
- // call forward, redirect or an action
153
- list($method, $parameters) = $e->getResultCallback();
154
- switch ($method) {
155
- case Mage_Core_Controller_Varien_Exception::RESULT_REDIRECT:
156
- list($path, $arguments) = $parameters;
157
- $this->_redirect($path, $arguments);
158
- break;
159
- case Mage_Core_Controller_Varien_Exception::RESULT_FORWARD:
160
- list($action, $controller, $module, $params) = $parameters;
161
- $this->_forward($action, $controller, $module, $params);
162
- break;
163
- default:
164
- $actionMethodName = $this->getActionMethodName($method);
165
- $this->getRequest()->setActionName($method);
166
- $this->$actionMethodName($method);
167
- break;
168
- }
169
  }
170
- }
171
 
172
- /**
173
- * get parameters from request which matching with configuration
174
- *
175
- * @throws Exception
176
- * @return array
177
- */
178
- private function _getParameters()
179
- {
180
- return array_merge(
181
- $this->_getParametersByAction('default', $this->getRequest()->getMethod()),
182
- $this->_getParametersByAction($this->getRequest()->getActionName(), $this->getRequest()->getMethod())
183
- );
184
  }
185
 
186
- private function _isEncryptionRequired($action, $method)
187
  {
188
- /** @var Varien_Simplexml_Element $doNotEncryptNode */
189
- $doNotEncryptNode = Mage::getConfig()->getNode("default/wCube/donotencrypt");
190
- if ($doNotEncryptNode && $doNotEncryptNode->hasChildren()) {
191
- $doNotEncryptArray = $doNotEncryptNode->asArray();
192
- $action = strtolower($action);
193
- $method = strtoupper($method);
194
- return !isset($doNotEncryptArray[$action][$method]);
 
 
 
 
 
195
  }
196
 
197
- return true;
198
  }
199
 
200
- private function _getParametersByAction($action, $method)
201
  {
202
- $parameters = array();
203
- $result = array();
204
- /** @var Varien_Simplexml_Element $actionNode */
205
- $actionNode = Mage::getConfig()->getNode("default/wCube/parameters/{$action}");
206
- if ($actionNode && $actionNode->hasChildren()) {
207
- $actionArray = $actionNode->asArray();
208
- if (array_key_exists($method, $actionArray)) {
209
- $parameters = $actionArray[$method];
210
- }
211
- }
212
- if (is_array($parameters)) {
213
- foreach ($parameters as $name => $options) {
214
- $value = $this->getRequest()->getParam($name, isset($options['default']) ? $options['default'] : null);
215
- if (isset($option['required']) && $options['required'] && $value === null) {
216
- throw new Exception('Missing required parameter:' . $name);
217
- }
218
- $result[$name] = $value;
219
- }
220
  }
221
-
222
- return $result;
223
  }
224
 
225
- public function hasAction($action)
 
 
 
 
 
 
 
226
  {
227
- return true;
 
 
 
 
 
228
  }
229
  }
1
  <?php
 
2
  /**
3
  * Magento
4
  *
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
  class SavvyCube_Connector_ApiController extends Mage_Core_Controller_Front_Action
22
  {
 
 
 
 
 
 
 
 
 
 
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
 
 
 
 
 
 
 
25
  protected function getAuthHelper()
26
  {
27
  return Mage::helper('wCube/authorization');
28
  }
29
 
30
+ public function indexAction()
31
  {
32
+ if (!$this->getAuthHelper()->auth($this->getRequest())) {
33
+ $error = array('401 Unauthorized', '');
34
+ } else {
35
+ $session = $this->getRequest()->getHeader('Sc-Session');
36
+ $key = $this->getAuthHelper()->getKeyBySession($session);
37
+ if (!$key) {
38
+ $error = array('401 Unauthorized', 'Session is missing');
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  } else {
40
+ $resource = $this->getRequest()->getActionName();
41
+ $method = $this->getRequest()->getMethod();
42
+ $params = $this->getRequest()->getParams();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
+ $method = strtolower($this->getRequest()->getMethod()) . "Method";
45
+ $apiResource = Mage::getModel('wCube/api_' . $resource);
 
 
46
 
47
+ if (!$apiResource) {
48
+ $error = array('500 Internal Server Error', 'No resource model');
49
+ } elseif (!is_callable(array($apiResource, $method))) {
50
+ $error = array('500 Internal Server Error', 'Unknown method');
51
+ } elseif ($apiResource->init($params)->$method()) {
52
+ $apiResource->formatResponse($key);
53
+ } else {
54
+ $error = $apiResource->error;
55
  }
56
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
 
58
 
59
+ if (isset($error)) {
60
+ list ($header, $body) = $error;
61
+ Mage::app()->getResponse()
62
+ ->setHeader('HTTP/1.1', $header)
63
+ ->setBody($body);
64
+ }
 
 
 
 
 
 
65
  }
66
 
67
+ public function authAction()
68
  {
69
+ if (!$this->getAuthHelper()->auth($this->getRequest())) {
70
+ Mage::app()->getResponse()
71
+ ->setHeader('HTTP/1.1', '401 Unauthorized');
72
+ } else {
73
+ $this->getAuthHelper()->getResource()->cleanSession();
74
+ $this->getAuthHelper()->getResource()->cleanNonce();
75
+ $key = $this->getRequest()->getParam('key');
76
+ $session = $this->getAuthHelper()->getResource()->createSession($key);
77
+ $key = $this->getAuthHelper()->getKeyBySession($session);
78
+ $key = base64_encode($this->getAuthHelper()->getScRsa()->encrypt($key));
79
+ Mage::app()->getResponse()->setHeader('Sc-Session', $session);
80
+ Mage::app()->getResponse()->setHeader('Sc-Key', $key);
81
  }
82
 
 
83
  }
84
 
85
+ public function checkAction()
86
  {
87
+ $session = (int)$this->getRequest()->getParam('session');
88
+ $result = $this->getAuthHelper()->candidateSignature($session);
89
+ if ($result) {
90
+ list($iv, $signature) = $result;
91
+ Mage::app()->getResponse()->setHeader('Sc-Sig', $signature);
92
+ Mage::app()->getResponse()->setHeader('Sc-Iv', $iv);
93
+ } else {
94
+ Mage::app()->getResponse()
95
+ ->setHeader('HTTP/1.1', '401 Unauthorized');
 
 
 
 
 
 
 
 
 
96
  }
 
 
97
  }
98
 
99
+
100
+ /**
101
+ * Retrieve action method name
102
+ *
103
+ * @param string $action
104
+ * @return string
105
+ */
106
+ public function getActionMethodName($action)
107
  {
108
+ if (strtolower($action) == 'auth')
109
+ return 'authAction';
110
+ if (strtolower($action) == 'check')
111
+ return 'checkAction';
112
+
113
+ return 'indexAction';
114
  }
115
  }
app/code/community/SavvyCube/Connector/controllers/SavvycubeController.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ class SavvyCube_Connector_SavvycubeController extends Mage_Adminhtml_Controller_Action
22
+ {
23
+ /**
24
+ * Authorization Helper
25
+ *
26
+ * @return SavvyCube_Connector_Helper_Authorization
27
+ */
28
+ protected function getAuthHelper()
29
+ {
30
+ return Mage::helper('wCube/authorization');
31
+ }
32
+
33
+ public function indexAction()
34
+ {
35
+ $this->getAuthHelper()->generateKeys();
36
+ $this->getAuthHelper()->cleanCache();
37
+ Mage::app()->getResponse()->setRedirect(
38
+ $this->getAuthHelper()->getActivationUrl()
39
+ );
40
+ }
41
+
42
+ public function activateAction()
43
+ {
44
+ $token = base64_decode($this->getRequest()->getParam('token'));
45
+ $session = (int)$this->getRequest()->getParam('session');
46
+ if ($this->getAuthHelper()->promoteCandidateKeys($session)) {
47
+ $this->getAuthHelper()->setToken($token);
48
+ $this->getAuthHelper()->cleanCache();
49
+ $finalUrl = $this->getUrl(
50
+ 'adminhtml/system_config/edit',
51
+ array('section' => 'w_cube')
52
+ );
53
+ Mage::app()->getResponse()->setRedirect($finalUrl);
54
+ } else {
55
+ Mage::app()->getResponse()
56
+ ->setHeader('HTTP/1.1', '401 Unauthorized');
57
+ }
58
+ }
59
+ public function _isAllowed()
60
+ {
61
+ return Mage::getSingleton('admin/session')
62
+ ->isAllowed('admin/system/config/w_cube');
63
+ }
64
+
65
+ }
app/code/community/SavvyCube/Connector/etc/adminhtml.xml CHANGED
@@ -1,23 +1,24 @@
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
- * Magento
5
- *
6
- * NOTICE OF LICENSE
7
- *
8
- * This source file is subject to the Open Software License (OSL 3.0)
9
- * that is bundled with this package in the file LICENSE.txt.
10
- * It is also available through the world-wide-web at this URL:
11
- * http://opensource.org/licenses/osl-3.0.php
12
- * If you did not receive a copy of the license and are unable to
13
- * obtain it through the world-wide-web, please send an email
14
- * to license@savvycube.com so we can send you a copy immediately.
15
- *
16
- * @category SavvyCube
17
- * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
19
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
- */
 
21
  -->
22
  <config>
23
  <acl>
@@ -28,9 +29,9 @@
28
  <children>
29
  <config>
30
  <children>
31
- <wCube translate="title" module="wCube">
32
  <title>SavvyCube Connector Settings</title>
33
- </wCube>
34
  </children>
35
  </config>
36
  </children>
@@ -39,4 +40,4 @@
39
  </admin>
40
  </resources>
41
  </acl>
42
- </config>
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@savvycube.com so we can send you a copy immediately.
15
+ *
16
+ * @category SavvyCube
17
+ * @package SavvyCube_Connector
18
+ * @copyright Copyright (c) 2017 SavvyCube
19
+ * SavvyCube is a trademark of Webtex Solutions, LLC
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
  -->
23
  <config>
24
  <acl>
29
  <children>
30
  <config>
31
  <children>
32
+ <w_cube translate="title" module="wCube">
33
  <title>SavvyCube Connector Settings</title>
34
+ </w_cube>
35
  </children>
36
  </config>
37
  </children>
40
  </admin>
41
  </resources>
42
  </acl>
43
+ </config>
app/code/community/SavvyCube/Connector/etc/config.xml CHANGED
@@ -1,28 +1,29 @@
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
- * Magento
5
- *
6
- * NOTICE OF LICENSE
7
- *
8
- * This source file is subject to the Open Software License (OSL 3.0)
9
- * that is bundled with this package in the file LICENSE.txt.
10
- * It is also available through the world-wide-web at this URL:
11
- * http://opensource.org/licenses/osl-3.0.php
12
- * If you did not receive a copy of the license and are unable to
13
- * obtain it through the world-wide-web, please send an email
14
- * to license@savvycube.com so we can send you a copy immediately.
15
- *
16
- * @category SavvyCube
17
- * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
19
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
- */
 
21
  -->
22
  <config>
23
  <modules>
24
  <SavvyCube_Connector>
25
- <version>0.0.7</version>
26
  </SavvyCube_Connector>
27
  </modules>
28
  <global>
@@ -35,8 +36,11 @@
35
  <class>SavvyCube_Connector_Model_Resource</class>
36
  <entities>
37
  <nonce>
38
- <table>wCube_nonce_cache</table>
39
  </nonce>
 
 
 
40
  </entities>
41
  </wCube_resource>
42
  </models>
@@ -61,89 +65,39 @@
61
  </global>
62
  <admin>
63
  <routers>
64
- <wCubeAdmin>
65
- <use>admin</use>
66
  <args>
67
- <module>SavvyCube_Connector</module>
68
- <frontName>wCubeAdmin</frontName>
 
69
  </args>
70
- </wCubeAdmin>
71
  </routers>
72
  </admin>
73
  <frontend>
 
 
 
 
 
 
 
74
  <routers>
75
- <wCube>
76
  <use>standard</use>
77
  <args>
78
  <module>SavvyCube_Connector</module>
79
- <frontName>wCube</frontName>
80
  </args>
81
- </wCube>
82
  </routers>
83
  </frontend>
84
  <default>
85
- <wCube>
86
- <cube_crypt>
87
- <open_key_file_path><![CDATA[cert/x509.crt]]></open_key_file_path>
88
- <consumer_endpoint><![CDATA[http://app.savvycube.com/]]></consumer_endpoint>
89
- <nonce_lifetime>5</nonce_lifetime>
90
- </cube_crypt>
91
- <parameters>
92
- <default>
93
- <GET>
94
- <offset/>
95
- <count/>
96
- <from_date/>
97
- <to_date/>
98
- </GET>
99
- </default>
100
- <address>
101
- <GET/>
102
- </address>
103
- <order>
104
- <GET/>
105
- </order>
106
- <orderitem>
107
- <GET/>
108
- </orderitem>
109
- <invoice>
110
- <GET/>
111
- </invoice>
112
- <invoiceitem>
113
- <GET/>
114
- </invoiceitem>
115
- <refund>
116
- <GET/>
117
- </refund>
118
- <refunditem>
119
- <GET/>
120
- </refunditem>
121
- <shipment>
122
- <GET/>
123
- </shipment>
124
- <shipmentitem>
125
- <GET/>
126
- </shipmentitem>
127
- <transaction>
128
- <GET/>
129
- </transaction>
130
- <version>
131
- <GET>
132
- <version/>
133
- </GET>
134
- </version>
135
- <notification>
136
- <GET>
137
- <description/>
138
- <title/>
139
- </GET>
140
- </notification>
141
- </parameters>
142
- <donotencrypt>
143
- <notification>
144
- <GET/>
145
- </notification>
146
- </donotencrypt>
147
- </wCube>
148
  </default>
149
  </config>
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@savvycube.com so we can send you a copy immediately.
15
+ *
16
+ * @category SavvyCube
17
+ * @package SavvyCube_Connector
18
+ * @copyright Copyright (c) 2017 SavvyCube
19
+ * SavvyCube is a trademark of Webtex Solutions, LLC
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
  -->
23
  <config>
24
  <modules>
25
  <SavvyCube_Connector>
26
+ <version>2.0.3</version>
27
  </SavvyCube_Connector>
28
  </modules>
29
  <global>
36
  <class>SavvyCube_Connector_Model_Resource</class>
37
  <entities>
38
  <nonce>
39
+ <table>savvycube_nonce</table>
40
  </nonce>
41
+ <session>
42
+ <table>savvycube_session</table>
43
+ </session>
44
  </entities>
45
  </wCube_resource>
46
  </models>
65
  </global>
66
  <admin>
67
  <routers>
68
+ <adminhtml>
 
69
  <args>
70
+ <modules>
71
+ <wCube before="Mage_Adminhtml">SavvyCube_Connector</wCube>
72
+ </modules>
73
  </args>
74
+ </adminhtml>
75
  </routers>
76
  </admin>
77
  <frontend>
78
+ <layout>
79
+ <updates>
80
+ <wCube>
81
+ <file>wCube/layout.xml</file>
82
+ </wCube>
83
+ </updates>
84
+ </layout>
85
  <routers>
86
+ <savvycube>
87
  <use>standard</use>
88
  <args>
89
  <module>SavvyCube_Connector</module>
90
+ <frontName>savvycube</frontName>
91
  </args>
92
+ </savvycube>
93
  </routers>
94
  </frontend>
95
  <default>
96
+ <w_cube>
97
+ <settings>
98
+ <priv backend_model="adminhtml/system_config_backend_encrypted" />
99
+ <savvy_url><![CDATA[https://appbeta.savvycube.com/]]></savvy_url>
100
+ </settings>
101
+ </w_cube>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  </default>
103
  </config>
app/code/community/SavvyCube/Connector/etc/system.xml CHANGED
@@ -1,59 +1,69 @@
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
- * Magento
5
- *
6
- * NOTICE OF LICENSE
7
- *
8
- * This source file is subject to the Open Software License (OSL 3.0)
9
- * that is bundled with this package in the file LICENSE.txt.
10
- * It is also available through the world-wide-web at this URL:
11
- * http://opensource.org/licenses/osl-3.0.php
12
- * If you did not receive a copy of the license and are unable to
13
- * obtain it through the world-wide-web, please send an email
14
- * to license@savvycube.com so we can send you a copy immediately.
15
- *
16
- * @category SavvyCube
17
- * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
19
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
- */
 
21
  -->
22
  <config>
23
  <sections>
24
- <wCube module="wCube" translate="label">
25
  <label>SavvyCube Connector</label>
26
  <sort_order>200</sort_order>
27
  <show_in_default>1</show_in_default>
28
  <tab>service</tab>
29
  <groups>
30
- <module_version translate="label">
31
- <label>Module Version Info</label>
32
- <sort_order>100</sort_order>
33
  <show_in_default>1</show_in_default>
 
34
  <fields>
35
  <version>
36
- <label>Version</label>
37
- <sort_order>2</sort_order>
38
  <show_in_default>1</show_in_default>
39
  <frontend_model>wCube/config_version</frontend_model>
 
40
  </version>
41
- </fields>
42
- </module_version>
43
- <general_settings translate="label">
44
- <label>General Settings</label>
45
- <sort_order>100</sort_order>
46
- <show_in_default>1</show_in_default>
47
- <fields>
48
  <activation>
49
- <label>Activate Connector / Refresh Activation</label>
50
- <sort_order>2</sort_order>
51
  <show_in_default>1</show_in_default>
52
  <frontend_model>wCube/config_activate</frontend_model>
 
53
  </activation>
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  </fields>
55
- </general_settings>
56
  </groups>
57
- </wCube>
58
  </sections>
59
- </config>
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@savvycube.com so we can send you a copy immediately.
15
+ *
16
+ * @category SavvyCube
17
+ * @package SavvyCube_Connector
18
+ * @copyright Copyright (c) 2017 SavvyCube
19
+ * SavvyCube is a trademark of Webtex Solutions, LLC
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
  -->
23
  <config>
24
  <sections>
25
+ <w_cube module="wCube" translate="label">
26
  <label>SavvyCube Connector</label>
27
  <sort_order>200</sort_order>
28
  <show_in_default>1</show_in_default>
29
  <tab>service</tab>
30
  <groups>
31
+ <settings translate="label">
32
+ <label>General Settings</label>
33
+ <sort_order>0</sort_order>
34
  <show_in_default>1</show_in_default>
35
+ <expanded>1</expanded>
36
  <fields>
37
  <version>
38
+ <label>SavvyCube Connector version:</label>
39
+ <sort_order>0</sort_order>
40
  <show_in_default>1</show_in_default>
41
  <frontend_model>wCube/config_version</frontend_model>
42
+ <frontend_type>label</frontend_type>
43
  </version>
 
 
 
 
 
 
 
44
  <activation>
45
+ <label>Connect or reconnect the store:</label>
46
+ <sort_order>0</sort_order>
47
  <show_in_default>1</show_in_default>
48
  <frontend_model>wCube/config_activate</frontend_model>
49
+ <frontend_type>button</frontend_type>
50
  </activation>
51
+ <savvy_url>
52
+ <label>SavvyCube URL:</label>
53
+ <sort_order>0</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <frontend_type>link</frontend_type>
56
+ </savvy_url>
57
+ <base_url>
58
+ <label>Store URL (must be visible online):</label>
59
+ <frontend_type>text</frontend_type>
60
+ <sort_order>0</sort_order>
61
+ <show_in_default>1</show_in_default>
62
+ <backend_model>wCube/baseurl</backend_model>
63
+ </base_url>
64
  </fields>
65
+ </settings>
66
  </groups>
67
+ </w_cube>
68
  </sections>
69
+ </config>
app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-install-0.0.1.php CHANGED
@@ -14,7 +14,8 @@
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
 
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
21
 
app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-install-0.0.9.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+
22
+ /* @var $installer Mage_Core_Model_Resource_Setup */
23
+ $installer = $this;
24
+
25
+ $installer->startSetup();
26
+
27
+ $installer->endSetup();
app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-install-2.0.0.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+
22
+ /* @var $installer Mage_Core_Model_Resource_Setup */
23
+ $installer = $this;
24
+
25
+ $installer->startSetup();
26
+
27
+ $nonceTable = $installer->getConnection()->newTable(
28
+ $installer->getTable('wCube/nonce')
29
+ )->addColumn(
30
+ 'nonce',
31
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
32
+ null,
33
+ array('nullable' => false),
34
+ 'nonce'
35
+ )->addColumn(
36
+ 'created_at',
37
+ Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
38
+ null,
39
+ array('default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT),
40
+ 'Created At'
41
+ );
42
+
43
+ $installer->getConnection()->createTable($nonceTable);
44
+
45
+ $sessionTable = $installer->getConnection()->newTable(
46
+ $installer->getTable('wCube/session')
47
+ )->addColumn(
48
+ 'session',
49
+ Varien_Db_Ddl_Table::TYPE_VARCHAR,
50
+ 40,
51
+ array('nullable' => false),
52
+ 'session name'
53
+ )->addColumn(
54
+ 'key',
55
+ Varien_Db_Ddl_Table::TYPE_TEXT,
56
+ null,
57
+ array('nullable' => false),
58
+ 'encryption key'
59
+ )->addColumn(
60
+ 'created_at',
61
+ Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
62
+ null,
63
+ array('default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT),
64
+ 'Created At'
65
+ );
66
+
67
+ $installer->getConnection()->createTable($sessionTable);
68
+
69
+ $installer->endSetup();
app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-upgrade-0.0.4-0.0.5.php CHANGED
@@ -14,10 +14,10 @@
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
 
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
-
21
  /* @var $installer Mage_Core_Model_Resource_Setup */
22
  $installer = $this;
23
 
@@ -29,4 +29,4 @@ $installer->getConnection()->modifyColumn(
29
  'BLOB'
30
  );
31
 
32
- $installer->endSetup();
14
  *
15
  * @category SavvyCube
16
  * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
  */
 
21
  /* @var $installer Mage_Core_Model_Resource_Setup */
22
  $installer = $this;
23
 
29
  'BLOB'
30
  );
31
 
32
+ $installer->endSetup();
app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-upgrade-0.0.8-0.0.9.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@savvycube.com so we can send you a copy immediately.
15
+ *
16
+ * @category SavvyCube
17
+ * @package SavvyCube_Connector
18
+ * @copyright Copyright (c) 2017 SavvyCube
19
+ * SavvyCube is a trademark of Webtex Solutions, LLC
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+
23
+ /* @var $installer Mage_Core_Model_Resource_Setup */
24
+ $installer = $this;
25
+
26
+ $installer->startSetup();
27
+
28
+ $installer->getConnection()->dropTable($installer->getTable('wCube_nonce_cache'));
29
+
30
+ $installer->endSetup();
app/code/community/SavvyCube/Connector/sql/wCube_setup/mysql4-upgrade-0.0.9-2.0.0.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ /* @var $installer Mage_Core_Model_Resource_Setup */
22
+ $installer = $this;
23
+
24
+ $installer->startSetup();
25
+
26
+ $nonceTable = $installer->getConnection()->newTable(
27
+ $installer->getTable('wCube/nonce')
28
+ )->addColumn(
29
+ 'nonce',
30
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
31
+ null,
32
+ array('nullable' => false),
33
+ 'nonce'
34
+ )->addColumn(
35
+ 'created_at',
36
+ Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
37
+ null,
38
+ array('default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT),
39
+ 'Created At'
40
+ );
41
+
42
+ $installer->getConnection()->createTable($nonceTable);
43
+
44
+ $sessionTable = $installer->getConnection()->newTable(
45
+ $installer->getTable('wCube/session')
46
+ )->addColumn(
47
+ 'session',
48
+ Varien_Db_Ddl_Table::TYPE_VARCHAR,
49
+ 40,
50
+ array('nullable' => false),
51
+ 'session name'
52
+ )->addColumn(
53
+ 'key',
54
+ Varien_Db_Ddl_Table::TYPE_TEXT,
55
+ null,
56
+ array('nullable' => false),
57
+ 'encryption key'
58
+ )->addColumn(
59
+ 'created_at',
60
+ Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
61
+ null,
62
+ array('default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT),
63
+ 'Created At'
64
+ );
65
+
66
+ $installer->getConnection()->createTable($sessionTable);
67
+
68
+ $installer->endSetup();
app/design/frontend/base/default/layout/wCube/layout.xml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@savvycube.com so we can send you a copy immediately.
15
+ *
16
+ * @category SavvyCube
17
+ * @package SavvyCube_Connector
18
+ * @copyright Copyright (c) 2017 SavvyCube
19
+ * SavvyCube is a trademark of Webtex Solutions, LLC
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ -->
23
+ <layout version="0.1.0">
24
+ <default>
25
+ <reference name="before_body_end">
26
+ <block type="core/template" name="ga_cart_tracking" template="wCube/ga.phtml" />
27
+ </reference>
28
+ </default>
29
+ </layout>
app/design/frontend/base/default/template/wCube/ga.phtml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@savvycube.com so we can send you a copy immediately.
14
+ *
15
+ * @category SavvyCube
16
+ * @package SavvyCube_Connector
17
+ * @copyright Copyright (c) 2017 SavvyCube
18
+ * SavvyCube is a trademark of Webtex Solutions, LLC
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ $quote = Mage::getModel('checkout/cart')->getQuote();
22
+ $quoteAlreadyTracked = Mage::getSingleton('core/session')
23
+ ->getData('wCube_track_' . $quote->getId());
24
+ $_helper = $this->helper('googleanalytics');
25
+ ?>
26
+ <?php if (!$quoteAlreadyTracked && $quote->getId() && !$this->helper('core/cookie')->isUserNotAllowSaveCookie()): ?>
27
+ <?php
28
+ Mage::getSingleton('core/session')->setData('wCube_track_' . $quote->getId(), true);
29
+ ?>
30
+ <?php if($_helper->isUseUniversalAnalytics()): ?>
31
+ <script type="text/javascript">
32
+ //<![CDATA[
33
+ (function(){ga('send', 'event', 'wCube', 'quote', <?php echo "'" . $quote->getId() . "'"; ?>);})()
34
+
35
+ //]]>
36
+ </script>
37
+ <?php else: ?>
38
+ <script type="text/javascript">
39
+ //<![CDATA[
40
+ var _gaq = _gaq || [];
41
+ _gaq.push(['_trackEvent', 'wCube', 'quote', <?php echo "'" . $quote->getId() . "'"; ?>]);
42
+ //]]>
43
+ </script>
44
+ <?php endif; ?>
45
+ <?php endif; ?>
app/etc/modules/SavvyCube_Connector.xml CHANGED
@@ -1,23 +1,24 @@
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
- * Magento
5
- *
6
- * NOTICE OF LICENSE
7
- *
8
- * This source file is subject to the Open Software License (OSL 3.0)
9
- * that is bundled with this package in the file LICENSE.txt.
10
- * It is also available through the world-wide-web at this URL:
11
- * http://opensource.org/licenses/osl-3.0.php
12
- * If you did not receive a copy of the license and are unable to
13
- * obtain it through the world-wide-web, please send an email
14
- * to license@savvycube.com so we can send you a copy immediately.
15
- *
16
- * @category SavvyCube
17
- * @package SavvyCube_Connector
18
- * @copyright Copyright (c) 2014 SavvyCube (http://www.savvycube.com). SavvyCube is a trademark of Webtex Solutions, LLC (http://www.webtexsoftware.com).
19
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
- */
 
21
  -->
22
  <config>
23
  <modules>
1
  <?xml version="1.0"?>
2
  <!--
3
  /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@savvycube.com so we can send you a copy immediately.
15
+ *
16
+ * @category SavvyCube
17
+ * @package SavvyCube_Connector
18
+ * @copyright Copyright (c) 2017 SavvyCube
19
+ * SavvyCube is a trademark of Webtex Solutions, LLC
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
  -->
23
  <config>
24
  <modules>
lib/sc/connector/vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInita4c351d989fd18be97aba0bc332b2b77::getLoader();
lib/sc/connector/vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+ private $classMapAuthoritative = false;
57
+ private $missingClasses = array();
58
+ private $apcuPrefix;
59
+
60
+ public function getPrefixes()
61
+ {
62
+ if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
64
+ }
65
+
66
+ return array();
67
+ }
68
+
69
+ public function getPrefixesPsr4()
70
+ {
71
+ return $this->prefixDirsPsr4;
72
+ }
73
+
74
+ public function getFallbackDirs()
75
+ {
76
+ return $this->fallbackDirsPsr0;
77
+ }
78
+
79
+ public function getFallbackDirsPsr4()
80
+ {
81
+ return $this->fallbackDirsPsr4;
82
+ }
83
+
84
+ public function getClassMap()
85
+ {
86
+ return $this->classMap;
87
+ }
88
+
89
+ /**
90
+ * @param array $classMap Class to filename map
91
+ */
92
+ public function addClassMap(array $classMap)
93
+ {
94
+ if ($this->classMap) {
95
+ $this->classMap = array_merge($this->classMap, $classMap);
96
+ } else {
97
+ $this->classMap = $classMap;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Registers a set of PSR-0 directories for a given prefix, either
103
+ * appending or prepending to the ones previously set for this prefix.
104
+ *
105
+ * @param string $prefix The prefix
106
+ * @param array|string $paths The PSR-0 root directories
107
+ * @param bool $prepend Whether to prepend the directories
108
+ */
109
+ public function add($prefix, $paths, $prepend = false)
110
+ {
111
+ if (!$prefix) {
112
+ if ($prepend) {
113
+ $this->fallbackDirsPsr0 = array_merge(
114
+ (array) $paths,
115
+ $this->fallbackDirsPsr0
116
+ );
117
+ } else {
118
+ $this->fallbackDirsPsr0 = array_merge(
119
+ $this->fallbackDirsPsr0,
120
+ (array) $paths
121
+ );
122
+ }
123
+
124
+ return;
125
+ }
126
+
127
+ $first = $prefix[0];
128
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
+
131
+ return;
132
+ }
133
+ if ($prepend) {
134
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
135
+ (array) $paths,
136
+ $this->prefixesPsr0[$first][$prefix]
137
+ );
138
+ } else {
139
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
140
+ $this->prefixesPsr0[$first][$prefix],
141
+ (array) $paths
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Registers a set of PSR-4 directories for a given namespace, either
148
+ * appending or prepending to the ones previously set for this namespace.
149
+ *
150
+ * @param string $prefix The prefix/namespace, with trailing '\\'
151
+ * @param array|string $paths The PSR-4 base directories
152
+ * @param bool $prepend Whether to prepend the directories
153
+ *
154
+ * @throws \InvalidArgumentException
155
+ */
156
+ public function addPsr4($prefix, $paths, $prepend = false)
157
+ {
158
+ if (!$prefix) {
159
+ // Register directories for the root namespace.
160
+ if ($prepend) {
161
+ $this->fallbackDirsPsr4 = array_merge(
162
+ (array) $paths,
163
+ $this->fallbackDirsPsr4
164
+ );
165
+ } else {
166
+ $this->fallbackDirsPsr4 = array_merge(
167
+ $this->fallbackDirsPsr4,
168
+ (array) $paths
169
+ );
170
+ }
171
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
+ // Register directories for a new namespace.
173
+ $length = strlen($prefix);
174
+ if ('\\' !== $prefix[$length - 1]) {
175
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
+ }
177
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
+ } elseif ($prepend) {
180
+ // Prepend directories for an already registered namespace.
181
+ $this->prefixDirsPsr4[$prefix] = array_merge(
182
+ (array) $paths,
183
+ $this->prefixDirsPsr4[$prefix]
184
+ );
185
+ } else {
186
+ // Append directories for an already registered namespace.
187
+ $this->prefixDirsPsr4[$prefix] = array_merge(
188
+ $this->prefixDirsPsr4[$prefix],
189
+ (array) $paths
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Registers a set of PSR-0 directories for a given prefix,
196
+ * replacing any others previously set for this prefix.
197
+ *
198
+ * @param string $prefix The prefix
199
+ * @param array|string $paths The PSR-0 base directories
200
+ */
201
+ public function set($prefix, $paths)
202
+ {
203
+ if (!$prefix) {
204
+ $this->fallbackDirsPsr0 = (array) $paths;
205
+ } else {
206
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Registers a set of PSR-4 directories for a given namespace,
212
+ * replacing any others previously set for this namespace.
213
+ *
214
+ * @param string $prefix The prefix/namespace, with trailing '\\'
215
+ * @param array|string $paths The PSR-4 base directories
216
+ *
217
+ * @throws \InvalidArgumentException
218
+ */
219
+ public function setPsr4($prefix, $paths)
220
+ {
221
+ if (!$prefix) {
222
+ $this->fallbackDirsPsr4 = (array) $paths;
223
+ } else {
224
+ $length = strlen($prefix);
225
+ if ('\\' !== $prefix[$length - 1]) {
226
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
+ }
228
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Turns on searching the include path for class files.
235
+ *
236
+ * @param bool $useIncludePath
237
+ */
238
+ public function setUseIncludePath($useIncludePath)
239
+ {
240
+ $this->useIncludePath = $useIncludePath;
241
+ }
242
+
243
+ /**
244
+ * Can be used to check if the autoloader uses the include path to check
245
+ * for classes.
246
+ *
247
+ * @return bool
248
+ */
249
+ public function getUseIncludePath()
250
+ {
251
+ return $this->useIncludePath;
252
+ }
253
+
254
+ /**
255
+ * Turns off searching the prefix and fallback directories for classes
256
+ * that have not been registered with the class map.
257
+ *
258
+ * @param bool $classMapAuthoritative
259
+ */
260
+ public function setClassMapAuthoritative($classMapAuthoritative)
261
+ {
262
+ $this->classMapAuthoritative = $classMapAuthoritative;
263
+ }
264
+
265
+ /**
266
+ * Should class lookup fail if not found in the current class map?
267
+ *
268
+ * @return bool
269
+ */
270
+ public function isClassMapAuthoritative()
271
+ {
272
+ return $this->classMapAuthoritative;
273
+ }
274
+
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
+ /**
296
+ * Registers this instance as an autoloader.
297
+ *
298
+ * @param bool $prepend Whether to prepend the autoloader or not
299
+ */
300
+ public function register($prepend = false)
301
+ {
302
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
+ }
304
+
305
+ /**
306
+ * Unregisters this instance as an autoloader.
307
+ */
308
+ public function unregister()
309
+ {
310
+ spl_autoload_unregister(array($this, 'loadClass'));
311
+ }
312
+
313
+ /**
314
+ * Loads the given class or interface.
315
+ *
316
+ * @param string $class The name of the class
317
+ * @return bool|null True if loaded, null otherwise
318
+ */
319
+ public function loadClass($class)
320
+ {
321
+ if ($file = $this->findFile($class)) {
322
+ includeFile($file);
323
+
324
+ return true;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Finds the path to the file where the class is defined.
330
+ *
331
+ * @param string $class The name of the class
332
+ *
333
+ * @return string|false The path if found, false otherwise
334
+ */
335
+ public function findFile($class)
336
+ {
337
+ // class map lookup
338
+ if (isset($this->classMap[$class])) {
339
+ return $this->classMap[$class];
340
+ }
341
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
+ return false;
343
+ }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
+
351
+ $file = $this->findFileWithExtension($class, '.php');
352
+
353
+ // Search for Hack files if we are running on HHVM
354
+ if (false === $file && defined('HHVM_VERSION')) {
355
+ $file = $this->findFileWithExtension($class, '.hh');
356
+ }
357
+
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
+ if (false === $file) {
363
+ // Remember that this class does not exist.
364
+ $this->missingClasses[$class] = true;
365
+ }
366
+
367
+ return $file;
368
+ }
369
+
370
+ private function findFileWithExtension($class, $ext)
371
+ {
372
+ // PSR-4 lookup
373
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
+
375
+ $first = $class[0];
376
+ if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath.'\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
383
+ $length = $this->prefixLengthsPsr4[$first][$search];
384
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
385
+ return $file;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ // PSR-4 fallback dirs
393
+ foreach ($this->fallbackDirsPsr4 as $dir) {
394
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
+ return $file;
396
+ }
397
+ }
398
+
399
+ // PSR-0 lookup
400
+ if (false !== $pos = strrpos($class, '\\')) {
401
+ // namespaced class name
402
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
+ } else {
405
+ // PEAR-like class name
406
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
+ }
408
+
409
+ if (isset($this->prefixesPsr0[$first])) {
410
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
+ if (0 === strpos($class, $prefix)) {
412
+ foreach ($dirs as $dir) {
413
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
+ return $file;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ // PSR-0 fallback dirs
422
+ foreach ($this->fallbackDirsPsr0 as $dir) {
423
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
+ return $file;
425
+ }
426
+ }
427
+
428
+ // PSR-0 include paths.
429
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
+ return $file;
431
+ }
432
+
433
+ return false;
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Scope isolated include.
439
+ *
440
+ * Prevents access to $this/self from included files.
441
+ */
442
+ function includeFile($file)
443
+ {
444
+ include $file;
445
+ }
lib/sc/connector/vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
lib/sc/connector/vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
lib/sc/connector/vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
10
+ '3919eeb97e98d4648304477f8ef734ba' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
11
+ );
lib/sc/connector/vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'System' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
10
+ 'Net' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
11
+ 'Math' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
12
+ 'File' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
13
+ 'Crypt' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
14
+ );
lib/sc/connector/vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
lib/sc/connector/vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInita4c351d989fd18be97aba0bc332b2b77
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInita4c351d989fd18be97aba0bc332b2b77', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInita4c351d989fd18be97aba0bc332b2b77', 'loadClassLoader'));
25
+
26
+ $includePaths = require __DIR__ . '/include_paths.php';
27
+ array_push($includePaths, get_include_path());
28
+ set_include_path(implode(PATH_SEPARATOR, $includePaths));
29
+
30
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
31
+ if ($useStaticLoader) {
32
+ require_once __DIR__ . '/autoload_static.php';
33
+
34
+ call_user_func(\Composer\Autoload\ComposerStaticInita4c351d989fd18be97aba0bc332b2b77::getInitializer($loader));
35
+ } else {
36
+ $map = require __DIR__ . '/autoload_namespaces.php';
37
+ foreach ($map as $namespace => $path) {
38
+ $loader->set($namespace, $path);
39
+ }
40
+
41
+ $map = require __DIR__ . '/autoload_psr4.php';
42
+ foreach ($map as $namespace => $path) {
43
+ $loader->setPsr4($namespace, $path);
44
+ }
45
+
46
+ $classMap = require __DIR__ . '/autoload_classmap.php';
47
+ if ($classMap) {
48
+ $loader->addClassMap($classMap);
49
+ }
50
+ }
51
+
52
+ $loader->register(true);
53
+
54
+ if ($useStaticLoader) {
55
+ $includeFiles = Composer\Autoload\ComposerStaticInita4c351d989fd18be97aba0bc332b2b77::$files;
56
+ } else {
57
+ $includeFiles = require __DIR__ . '/autoload_files.php';
58
+ }
59
+ foreach ($includeFiles as $fileIdentifier => $file) {
60
+ composerRequirea4c351d989fd18be97aba0bc332b2b77($fileIdentifier, $file);
61
+ }
62
+
63
+ return $loader;
64
+ }
65
+ }
66
+
67
+ function composerRequirea4c351d989fd18be97aba0bc332b2b77($fileIdentifier, $file)
68
+ {
69
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
70
+ require $file;
71
+
72
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
73
+ }
74
+ }
lib/sc/connector/vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInita4c351d989fd18be97aba0bc332b2b77
8
+ {
9
+ public static $files = array (
10
+ 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
11
+ '3919eeb97e98d4648304477f8ef734ba' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
12
+ );
13
+
14
+ public static $prefixesPsr0 = array (
15
+ 'S' =>
16
+ array (
17
+ 'System' =>
18
+ array (
19
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
20
+ ),
21
+ ),
22
+ 'N' =>
23
+ array (
24
+ 'Net' =>
25
+ array (
26
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
27
+ ),
28
+ ),
29
+ 'M' =>
30
+ array (
31
+ 'Math' =>
32
+ array (
33
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
34
+ ),
35
+ ),
36
+ 'F' =>
37
+ array (
38
+ 'File' =>
39
+ array (
40
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
41
+ ),
42
+ ),
43
+ 'C' =>
44
+ array (
45
+ 'Crypt' =>
46
+ array (
47
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
48
+ ),
49
+ ),
50
+ );
51
+
52
+ public static function getInitializer(ClassLoader $loader)
53
+ {
54
+ return \Closure::bind(function () use ($loader) {
55
+ $loader->prefixesPsr0 = ComposerStaticInita4c351d989fd18be97aba0bc332b2b77::$prefixesPsr0;
56
+
57
+ }, null, ClassLoader::class);
58
+ }
59
+ }
lib/sc/connector/vendor/composer/include_paths.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // include_paths.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ $vendorDir . '/phpseclib/phpseclib/phpseclib',
10
+ );
lib/sc/connector/vendor/composer/installed.json ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "phpseclib/phpseclib",
4
+ "version": "1.0.6",
5
+ "version_normalized": "1.0.6.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/phpseclib/phpseclib.git",
9
+ "reference": "aa8368ed12ef389f20d3932d051a7207471ecbab"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/aa8368ed12ef389f20d3932d051a7207471ecbab",
14
+ "reference": "aa8368ed12ef389f20d3932d051a7207471ecbab",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "php": ">=5.0.0"
19
+ },
20
+ "require-dev": {
21
+ "phing/phing": "~2.7",
22
+ "phpunit/phpunit": "~4.0",
23
+ "sami/sami": "~2.0",
24
+ "squizlabs/php_codesniffer": "~2.0"
25
+ },
26
+ "suggest": {
27
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
28
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.",
29
+ "pear-pear/PHP_Compat": "Install PHP_Compat to get phpseclib working on PHP < 5.0.0."
30
+ },
31
+ "time": "2017-05-08T05:58:24+00:00",
32
+ "type": "library",
33
+ "installation-source": "dist",
34
+ "autoload": {
35
+ "psr-0": {
36
+ "Crypt": "phpseclib/",
37
+ "File": "phpseclib/",
38
+ "Math": "phpseclib/",
39
+ "Net": "phpseclib/",
40
+ "System": "phpseclib/"
41
+ },
42
+ "files": [
43
+ "phpseclib/bootstrap.php",
44
+ "phpseclib/Crypt/Random.php"
45
+ ]
46
+ },
47
+ "notification-url": "https://packagist.org/downloads/",
48
+ "include-path": [
49
+ "phpseclib/"
50
+ ],
51
+ "license": [
52
+ "MIT"
53
+ ],
54
+ "authors": [
55
+ {
56
+ "name": "Jim Wigginton",
57
+ "email": "terrafrost@php.net",
58
+ "role": "Lead Developer"
59
+ },
60
+ {
61
+ "name": "Patrick Monnerat",
62
+ "email": "pm@datasphere.ch",
63
+ "role": "Developer"
64
+ },
65
+ {
66
+ "name": "Andreas Fischer",
67
+ "email": "bantu@phpbb.com",
68
+ "role": "Developer"
69
+ },
70
+ {
71
+ "name": "Hans-Jürgen Petrich",
72
+ "email": "petrich@tronic-media.com",
73
+ "role": "Developer"
74
+ },
75
+ {
76
+ "name": "Graham Campbell",
77
+ "email": "graham@alt-three.com",
78
+ "role": "Developer"
79
+ }
80
+ ],
81
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
82
+ "homepage": "http://phpseclib.sourceforge.net",
83
+ "keywords": [
84
+ "BigInteger",
85
+ "aes",
86
+ "asn.1",
87
+ "asn1",
88
+ "blowfish",
89
+ "crypto",
90
+ "cryptography",
91
+ "encryption",
92
+ "rsa",
93
+ "security",
94
+ "sftp",
95
+ "signature",
96
+ "signing",
97
+ "ssh",
98
+ "twofish",
99
+ "x.509",
100
+ "x509"
101
+ ]
102
+ }
103
+ ]
lib/sc/connector/vendor/phpseclib/phpseclib/AUTHORS ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ phpseclib Lead Developer: TerraFrost (Jim Wigginton)
2
+
3
+ phpseclib Developers: monnerat (Patrick Monnerat)
4
+ bantu (Andreas Fischer)
5
+ petrich (Hans-Jürgen Petrich)
6
+ GrahamCampbell (Graham Campbell)
lib/sc/connector/vendor/phpseclib/phpseclib/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright 2007-2016 TerraFrost and other contributors
2
+ http://phpseclib.sourceforge.net/
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
lib/sc/connector/vendor/phpseclib/phpseclib/README.md ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # phpseclib - PHP Secure Communications Library
2
+
3
+ [![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=1.0)](https://travis-ci.org/phpseclib/phpseclib)
4
+
5
+ MIT-licensed pure-PHP implementations of an arbitrary-precision integer
6
+ arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
7
+ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
8
+
9
+ * [Browse Git](https://github.com/phpseclib/phpseclib)
10
+ * [Code Coverage Report](https://coverage.phpseclib.org/1.0/latest/)
11
+
12
+ ## Documentation
13
+
14
+ * [Documentation / Manual](http://phpseclib.sourceforge.net/)
15
+ * [API Documentation](https://api.phpseclib.org/1.0/) (generated by Sami)
16
+
17
+ ## Branches
18
+
19
+ ### master
20
+
21
+ * Development Branch
22
+ * Unstable API
23
+ * Do not use in production
24
+
25
+ ### 2.0
26
+
27
+ * Modernized version of 1.0
28
+ * Minimum PHP version: 5.3.3
29
+ * PSR-4 autoloading with namespace rooted at `\phpseclib`
30
+ * Install via Composer: `composer require phpseclib/phpseclib ~2.0`
31
+
32
+ ### 1.0
33
+
34
+ * Long term support (LTS) release
35
+ * PHP4 compatible
36
+ * Composer compatible (PSR-0 autoloading)
37
+ * Install using Composer: `composer require phpseclib/phpseclib ~1.0`
38
+ * Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
39
+ * [Download 1.0.6 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.6.zip/download)
40
+
41
+ ## Support
42
+
43
+ Need Support?
44
+
45
+ * [Checkout Questions and Answers on Stack Overflow](http://stackoverflow.com/questions/tagged/phpseclib)
46
+ * [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new)
47
+ * [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use)
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork the Project
52
+
53
+ 2. Ensure you have Composer installed (see [Composer Download Instructions](https://getcomposer.org/download/))
54
+
55
+ 3. Install Development Dependencies
56
+
57
+ ``` sh
58
+ composer install
59
+ ```
60
+
61
+ 4. Create a Feature Branch
62
+
63
+ 5. (Recommended) Run the Test Suite
64
+
65
+ ``` sh
66
+ vendor/bin/phpunit
67
+ ```
68
+ 6. (Recommended) Check whether your code conforms to our Coding Standards by running
69
+
70
+ ``` sh
71
+ vendor/bin/phing -f build/build.xml sniff
72
+ ```
73
+
74
+ 7. Send us a Pull Request
lib/sc/connector/vendor/phpseclib/phpseclib/composer.json ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "phpseclib/phpseclib",
3
+ "type": "library",
4
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
5
+ "keywords": [
6
+ "security",
7
+ "crypto",
8
+ "cryptography",
9
+ "encryption",
10
+ "signature",
11
+ "signing",
12
+ "rsa",
13
+ "aes",
14
+ "blowfish",
15
+ "twofish",
16
+ "ssh",
17
+ "sftp",
18
+ "x509",
19
+ "x.509",
20
+ "asn1",
21
+ "asn.1",
22
+ "BigInteger"
23
+ ],
24
+ "homepage": "http://phpseclib.sourceforge.net",
25
+ "license": "MIT",
26
+ "authors": [
27
+ {
28
+ "name": "Jim Wigginton",
29
+ "email": "terrafrost@php.net",
30
+ "role": "Lead Developer"
31
+ },
32
+ {
33
+ "name": "Patrick Monnerat",
34
+ "email": "pm@datasphere.ch",
35
+ "role": "Developer"
36
+ },
37
+ {
38
+ "name": "Andreas Fischer",
39
+ "email": "bantu@phpbb.com",
40
+ "role": "Developer"
41
+ },
42
+ {
43
+ "name": "Hans-Jürgen Petrich",
44
+ "email": "petrich@tronic-media.com",
45
+ "role": "Developer"
46
+ },
47
+ {
48
+ "name": "Graham Campbell",
49
+ "email": "graham@alt-three.com",
50
+ "role": "Developer"
51
+ }
52
+ ],
53
+ "require": {
54
+ "php": ">=5.0.0"
55
+ },
56
+ "require-dev": {
57
+ "phing/phing": "~2.7",
58
+ "phpunit/phpunit": "~4.0",
59
+ "sami/sami": "~2.0",
60
+ "squizlabs/php_codesniffer": "~2.0"
61
+ },
62
+ "suggest": {
63
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.",
64
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
65
+ "pear-pear/PHP_Compat": "Install PHP_Compat to get phpseclib working on PHP < 5.0.0."
66
+ },
67
+ "include-path": ["phpseclib/"],
68
+ "autoload": {
69
+ "psr-0": {
70
+ "Crypt": "phpseclib/",
71
+ "File": "phpseclib/",
72
+ "Math": "phpseclib/",
73
+ "Net": "phpseclib/",
74
+ "System": "phpseclib/"
75
+ },
76
+ "files": [
77
+ "phpseclib/bootstrap.php",
78
+ "phpseclib/Crypt/Random.php"
79
+ ]
80
+ }
81
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/composer.lock ADDED
@@ -0,0 +1,1669 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "hash": "24648c5326ee237cd79bb0d311b16cb8",
8
+ "content-hash": "cec0167a357df0f3da215133e2424a6c",
9
+ "packages": [],
10
+ "packages-dev": [
11
+ {
12
+ "name": "doctrine/instantiator",
13
+ "version": "1.0.5",
14
+ "source": {
15
+ "type": "git",
16
+ "url": "https://github.com/doctrine/instantiator.git",
17
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
18
+ },
19
+ "dist": {
20
+ "type": "zip",
21
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
22
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
23
+ "shasum": ""
24
+ },
25
+ "require": {
26
+ "php": ">=5.3,<8.0-DEV"
27
+ },
28
+ "require-dev": {
29
+ "athletic/athletic": "~0.1.8",
30
+ "ext-pdo": "*",
31
+ "ext-phar": "*",
32
+ "phpunit/phpunit": "~4.0",
33
+ "squizlabs/php_codesniffer": "~2.0"
34
+ },
35
+ "type": "library",
36
+ "extra": {
37
+ "branch-alias": {
38
+ "dev-master": "1.0.x-dev"
39
+ }
40
+ },
41
+ "autoload": {
42
+ "psr-4": {
43
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
44
+ }
45
+ },
46
+ "notification-url": "https://packagist.org/downloads/",
47
+ "license": [
48
+ "MIT"
49
+ ],
50
+ "authors": [
51
+ {
52
+ "name": "Marco Pivetta",
53
+ "email": "ocramius@gmail.com",
54
+ "homepage": "http://ocramius.github.com/"
55
+ }
56
+ ],
57
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
58
+ "homepage": "https://github.com/doctrine/instantiator",
59
+ "keywords": [
60
+ "constructor",
61
+ "instantiate"
62
+ ],
63
+ "time": "2015-06-14 21:17:01"
64
+ },
65
+ {
66
+ "name": "michelf/php-markdown",
67
+ "version": "1.6.0",
68
+ "source": {
69
+ "type": "git",
70
+ "url": "https://github.com/michelf/php-markdown.git",
71
+ "reference": "156e56ee036505ec637d761ee62dc425d807183c"
72
+ },
73
+ "dist": {
74
+ "type": "zip",
75
+ "url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c",
76
+ "reference": "156e56ee036505ec637d761ee62dc425d807183c",
77
+ "shasum": ""
78
+ },
79
+ "require": {
80
+ "php": ">=5.3.0"
81
+ },
82
+ "type": "library",
83
+ "extra": {
84
+ "branch-alias": {
85
+ "dev-lib": "1.4.x-dev"
86
+ }
87
+ },
88
+ "autoload": {
89
+ "psr-0": {
90
+ "Michelf": ""
91
+ }
92
+ },
93
+ "notification-url": "https://packagist.org/downloads/",
94
+ "license": [
95
+ "BSD-3-Clause"
96
+ ],
97
+ "authors": [
98
+ {
99
+ "name": "Michel Fortin",
100
+ "email": "michel.fortin@michelf.ca",
101
+ "homepage": "https://michelf.ca/",
102
+ "role": "Developer"
103
+ },
104
+ {
105
+ "name": "John Gruber",
106
+ "homepage": "https://daringfireball.net/"
107
+ }
108
+ ],
109
+ "description": "PHP Markdown",
110
+ "homepage": "https://michelf.ca/projects/php-markdown/",
111
+ "keywords": [
112
+ "markdown"
113
+ ],
114
+ "time": "2015-12-24 01:37:31"
115
+ },
116
+ {
117
+ "name": "nikic/php-parser",
118
+ "version": "v0.9.5",
119
+ "source": {
120
+ "type": "git",
121
+ "url": "https://github.com/nikic/PHP-Parser.git",
122
+ "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb"
123
+ },
124
+ "dist": {
125
+ "type": "zip",
126
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ef70767475434bdb3615b43c327e2cae17ef12eb",
127
+ "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb",
128
+ "shasum": ""
129
+ },
130
+ "require": {
131
+ "ext-tokenizer": "*",
132
+ "php": ">=5.2"
133
+ },
134
+ "type": "library",
135
+ "extra": {
136
+ "branch-alias": {
137
+ "dev-master": "0.9-dev"
138
+ }
139
+ },
140
+ "autoload": {
141
+ "psr-0": {
142
+ "PHPParser": "lib/"
143
+ }
144
+ },
145
+ "notification-url": "https://packagist.org/downloads/",
146
+ "license": [
147
+ "BSD-3-Clause"
148
+ ],
149
+ "authors": [
150
+ {
151
+ "name": "Nikita Popov"
152
+ }
153
+ ],
154
+ "description": "A PHP parser written in PHP",
155
+ "keywords": [
156
+ "parser",
157
+ "php"
158
+ ],
159
+ "time": "2014-07-23 18:24:17"
160
+ },
161
+ {
162
+ "name": "phing/phing",
163
+ "version": "2.14.0",
164
+ "source": {
165
+ "type": "git",
166
+ "url": "https://github.com/phingofficial/phing.git",
167
+ "reference": "7dd73c83c377623def54b58121f46b4dcb35dd61"
168
+ },
169
+ "dist": {
170
+ "type": "zip",
171
+ "url": "https://api.github.com/repos/phingofficial/phing/zipball/7dd73c83c377623def54b58121f46b4dcb35dd61",
172
+ "reference": "7dd73c83c377623def54b58121f46b4dcb35dd61",
173
+ "shasum": ""
174
+ },
175
+ "require": {
176
+ "php": ">=5.2.0"
177
+ },
178
+ "require-dev": {
179
+ "ext-pdo_sqlite": "*",
180
+ "lastcraft/simpletest": "@dev",
181
+ "mikey179/vfsstream": "^1.6",
182
+ "pdepend/pdepend": "2.x",
183
+ "pear/archive_tar": "1.4.x",
184
+ "pear/http_request2": "dev-trunk",
185
+ "pear/net_growl": "dev-trunk",
186
+ "pear/pear-core-minimal": "1.10.1",
187
+ "pear/versioncontrol_git": "@dev",
188
+ "pear/versioncontrol_svn": "~0.5",
189
+ "phpdocumentor/phpdocumentor": "2.x",
190
+ "phploc/phploc": "~2.0.6",
191
+ "phpmd/phpmd": "~2.2",
192
+ "phpunit/phpunit": ">=3.7",
193
+ "sebastian/git": "~1.0",
194
+ "sebastian/phpcpd": "2.x",
195
+ "squizlabs/php_codesniffer": "~2.2",
196
+ "symfony/yaml": "~2.7"
197
+ },
198
+ "suggest": {
199
+ "pdepend/pdepend": "PHP version of JDepend",
200
+ "pear/archive_tar": "Tar file management class",
201
+ "pear/versioncontrol_git": "A library that provides OO interface to handle Git repository",
202
+ "pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system",
203
+ "phpdocumentor/phpdocumentor": "Documentation Generator for PHP",
204
+ "phploc/phploc": "A tool for quickly measuring the size of a PHP project",
205
+ "phpmd/phpmd": "PHP version of PMD tool",
206
+ "phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information",
207
+ "phpunit/phpunit": "The PHP Unit Testing Framework",
208
+ "sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code",
209
+ "tedivm/jshrink": "Javascript Minifier built in PHP"
210
+ },
211
+ "bin": [
212
+ "bin/phing"
213
+ ],
214
+ "type": "library",
215
+ "extra": {
216
+ "branch-alias": {
217
+ "dev-master": "2.14.x-dev"
218
+ }
219
+ },
220
+ "autoload": {
221
+ "classmap": [
222
+ "classes/phing/"
223
+ ]
224
+ },
225
+ "notification-url": "https://packagist.org/downloads/",
226
+ "include-path": [
227
+ "classes"
228
+ ],
229
+ "license": [
230
+ "LGPL-3.0"
231
+ ],
232
+ "authors": [
233
+ {
234
+ "name": "Michiel Rook",
235
+ "email": "mrook@php.net"
236
+ },
237
+ {
238
+ "name": "Phing Community",
239
+ "homepage": "https://www.phing.info/trac/wiki/Development/Contributors"
240
+ }
241
+ ],
242
+ "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.",
243
+ "homepage": "https://www.phing.info/",
244
+ "keywords": [
245
+ "build",
246
+ "phing",
247
+ "task",
248
+ "tool"
249
+ ],
250
+ "time": "2016-03-10 21:39:23"
251
+ },
252
+ {
253
+ "name": "phpdocumentor/reflection-docblock",
254
+ "version": "2.0.4",
255
+ "source": {
256
+ "type": "git",
257
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
258
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
259
+ },
260
+ "dist": {
261
+ "type": "zip",
262
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
263
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
264
+ "shasum": ""
265
+ },
266
+ "require": {
267
+ "php": ">=5.3.3"
268
+ },
269
+ "require-dev": {
270
+ "phpunit/phpunit": "~4.0"
271
+ },
272
+ "suggest": {
273
+ "dflydev/markdown": "~1.0",
274
+ "erusev/parsedown": "~1.0"
275
+ },
276
+ "type": "library",
277
+ "extra": {
278
+ "branch-alias": {
279
+ "dev-master": "2.0.x-dev"
280
+ }
281
+ },
282
+ "autoload": {
283
+ "psr-0": {
284
+ "phpDocumentor": [
285
+ "src/"
286
+ ]
287
+ }
288
+ },
289
+ "notification-url": "https://packagist.org/downloads/",
290
+ "license": [
291
+ "MIT"
292
+ ],
293
+ "authors": [
294
+ {
295
+ "name": "Mike van Riel",
296
+ "email": "mike.vanriel@naenius.com"
297
+ }
298
+ ],
299
+ "time": "2015-02-03 12:10:50"
300
+ },
301
+ {
302
+ "name": "phpspec/prophecy",
303
+ "version": "v1.6.0",
304
+ "source": {
305
+ "type": "git",
306
+ "url": "https://github.com/phpspec/prophecy.git",
307
+ "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972"
308
+ },
309
+ "dist": {
310
+ "type": "zip",
311
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972",
312
+ "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972",
313
+ "shasum": ""
314
+ },
315
+ "require": {
316
+ "doctrine/instantiator": "^1.0.2",
317
+ "php": "^5.3|^7.0",
318
+ "phpdocumentor/reflection-docblock": "~2.0",
319
+ "sebastian/comparator": "~1.1",
320
+ "sebastian/recursion-context": "~1.0"
321
+ },
322
+ "require-dev": {
323
+ "phpspec/phpspec": "~2.0"
324
+ },
325
+ "type": "library",
326
+ "extra": {
327
+ "branch-alias": {
328
+ "dev-master": "1.5.x-dev"
329
+ }
330
+ },
331
+ "autoload": {
332
+ "psr-0": {
333
+ "Prophecy\\": "src/"
334
+ }
335
+ },
336
+ "notification-url": "https://packagist.org/downloads/",
337
+ "license": [
338
+ "MIT"
339
+ ],
340
+ "authors": [
341
+ {
342
+ "name": "Konstantin Kudryashov",
343
+ "email": "ever.zet@gmail.com",
344
+ "homepage": "http://everzet.com"
345
+ },
346
+ {
347
+ "name": "Marcello Duarte",
348
+ "email": "marcello.duarte@gmail.com"
349
+ }
350
+ ],
351
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
352
+ "homepage": "https://github.com/phpspec/prophecy",
353
+ "keywords": [
354
+ "Double",
355
+ "Dummy",
356
+ "fake",
357
+ "mock",
358
+ "spy",
359
+ "stub"
360
+ ],
361
+ "time": "2016-02-15 07:46:21"
362
+ },
363
+ {
364
+ "name": "phpunit/php-code-coverage",
365
+ "version": "2.2.4",
366
+ "source": {
367
+ "type": "git",
368
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
369
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
370
+ },
371
+ "dist": {
372
+ "type": "zip",
373
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
374
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
375
+ "shasum": ""
376
+ },
377
+ "require": {
378
+ "php": ">=5.3.3",
379
+ "phpunit/php-file-iterator": "~1.3",
380
+ "phpunit/php-text-template": "~1.2",
381
+ "phpunit/php-token-stream": "~1.3",
382
+ "sebastian/environment": "^1.3.2",
383
+ "sebastian/version": "~1.0"
384
+ },
385
+ "require-dev": {
386
+ "ext-xdebug": ">=2.1.4",
387
+ "phpunit/phpunit": "~4"
388
+ },
389
+ "suggest": {
390
+ "ext-dom": "*",
391
+ "ext-xdebug": ">=2.2.1",
392
+ "ext-xmlwriter": "*"
393
+ },
394
+ "type": "library",
395
+ "extra": {
396
+ "branch-alias": {
397
+ "dev-master": "2.2.x-dev"
398
+ }
399
+ },
400
+ "autoload": {
401
+ "classmap": [
402
+ "src/"
403
+ ]
404
+ },
405
+ "notification-url": "https://packagist.org/downloads/",
406
+ "license": [
407
+ "BSD-3-Clause"
408
+ ],
409
+ "authors": [
410
+ {
411
+ "name": "Sebastian Bergmann",
412
+ "email": "sb@sebastian-bergmann.de",
413
+ "role": "lead"
414
+ }
415
+ ],
416
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
417
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
418
+ "keywords": [
419
+ "coverage",
420
+ "testing",
421
+ "xunit"
422
+ ],
423
+ "time": "2015-10-06 15:47:00"
424
+ },
425
+ {
426
+ "name": "phpunit/php-file-iterator",
427
+ "version": "1.4.1",
428
+ "source": {
429
+ "type": "git",
430
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
431
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
432
+ },
433
+ "dist": {
434
+ "type": "zip",
435
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
436
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
437
+ "shasum": ""
438
+ },
439
+ "require": {
440
+ "php": ">=5.3.3"
441
+ },
442
+ "type": "library",
443
+ "extra": {
444
+ "branch-alias": {
445
+ "dev-master": "1.4.x-dev"
446
+ }
447
+ },
448
+ "autoload": {
449
+ "classmap": [
450
+ "src/"
451
+ ]
452
+ },
453
+ "notification-url": "https://packagist.org/downloads/",
454
+ "license": [
455
+ "BSD-3-Clause"
456
+ ],
457
+ "authors": [
458
+ {
459
+ "name": "Sebastian Bergmann",
460
+ "email": "sb@sebastian-bergmann.de",
461
+ "role": "lead"
462
+ }
463
+ ],
464
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
465
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
466
+ "keywords": [
467
+ "filesystem",
468
+ "iterator"
469
+ ],
470
+ "time": "2015-06-21 13:08:43"
471
+ },
472
+ {
473
+ "name": "phpunit/php-text-template",
474
+ "version": "1.2.1",
475
+ "source": {
476
+ "type": "git",
477
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
478
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
479
+ },
480
+ "dist": {
481
+ "type": "zip",
482
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
483
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
484
+ "shasum": ""
485
+ },
486
+ "require": {
487
+ "php": ">=5.3.3"
488
+ },
489
+ "type": "library",
490
+ "autoload": {
491
+ "classmap": [
492
+ "src/"
493
+ ]
494
+ },
495
+ "notification-url": "https://packagist.org/downloads/",
496
+ "license": [
497
+ "BSD-3-Clause"
498
+ ],
499
+ "authors": [
500
+ {
501
+ "name": "Sebastian Bergmann",
502
+ "email": "sebastian@phpunit.de",
503
+ "role": "lead"
504
+ }
505
+ ],
506
+ "description": "Simple template engine.",
507
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
508
+ "keywords": [
509
+ "template"
510
+ ],
511
+ "time": "2015-06-21 13:50:34"
512
+ },
513
+ {
514
+ "name": "phpunit/php-timer",
515
+ "version": "1.0.7",
516
+ "source": {
517
+ "type": "git",
518
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
519
+ "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b"
520
+ },
521
+ "dist": {
522
+ "type": "zip",
523
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
524
+ "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
525
+ "shasum": ""
526
+ },
527
+ "require": {
528
+ "php": ">=5.3.3"
529
+ },
530
+ "type": "library",
531
+ "autoload": {
532
+ "classmap": [
533
+ "src/"
534
+ ]
535
+ },
536
+ "notification-url": "https://packagist.org/downloads/",
537
+ "license": [
538
+ "BSD-3-Clause"
539
+ ],
540
+ "authors": [
541
+ {
542
+ "name": "Sebastian Bergmann",
543
+ "email": "sb@sebastian-bergmann.de",
544
+ "role": "lead"
545
+ }
546
+ ],
547
+ "description": "Utility class for timing",
548
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
549
+ "keywords": [
550
+ "timer"
551
+ ],
552
+ "time": "2015-06-21 08:01:12"
553
+ },
554
+ {
555
+ "name": "phpunit/php-token-stream",
556
+ "version": "1.4.8",
557
+ "source": {
558
+ "type": "git",
559
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
560
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
561
+ },
562
+ "dist": {
563
+ "type": "zip",
564
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
565
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
566
+ "shasum": ""
567
+ },
568
+ "require": {
569
+ "ext-tokenizer": "*",
570
+ "php": ">=5.3.3"
571
+ },
572
+ "require-dev": {
573
+ "phpunit/phpunit": "~4.2"
574
+ },
575
+ "type": "library",
576
+ "extra": {
577
+ "branch-alias": {
578
+ "dev-master": "1.4-dev"
579
+ }
580
+ },
581
+ "autoload": {
582
+ "classmap": [
583
+ "src/"
584
+ ]
585
+ },
586
+ "notification-url": "https://packagist.org/downloads/",
587
+ "license": [
588
+ "BSD-3-Clause"
589
+ ],
590
+ "authors": [
591
+ {
592
+ "name": "Sebastian Bergmann",
593
+ "email": "sebastian@phpunit.de"
594
+ }
595
+ ],
596
+ "description": "Wrapper around PHP's tokenizer extension.",
597
+ "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
598
+ "keywords": [
599
+ "tokenizer"
600
+ ],
601
+ "time": "2015-09-15 10:49:45"
602
+ },
603
+ {
604
+ "name": "phpunit/phpunit",
605
+ "version": "4.8.24",
606
+ "source": {
607
+ "type": "git",
608
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
609
+ "reference": "a1066c562c52900a142a0e2bbf0582994671385e"
610
+ },
611
+ "dist": {
612
+ "type": "zip",
613
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1066c562c52900a142a0e2bbf0582994671385e",
614
+ "reference": "a1066c562c52900a142a0e2bbf0582994671385e",
615
+ "shasum": ""
616
+ },
617
+ "require": {
618
+ "ext-dom": "*",
619
+ "ext-json": "*",
620
+ "ext-pcre": "*",
621
+ "ext-reflection": "*",
622
+ "ext-spl": "*",
623
+ "php": ">=5.3.3",
624
+ "phpspec/prophecy": "^1.3.1",
625
+ "phpunit/php-code-coverage": "~2.1",
626
+ "phpunit/php-file-iterator": "~1.4",
627
+ "phpunit/php-text-template": "~1.2",
628
+ "phpunit/php-timer": ">=1.0.6",
629
+ "phpunit/phpunit-mock-objects": "~2.3",
630
+ "sebastian/comparator": "~1.1",
631
+ "sebastian/diff": "~1.2",
632
+ "sebastian/environment": "~1.3",
633
+ "sebastian/exporter": "~1.2",
634
+ "sebastian/global-state": "~1.0",
635
+ "sebastian/version": "~1.0",
636
+ "symfony/yaml": "~2.1|~3.0"
637
+ },
638
+ "suggest": {
639
+ "phpunit/php-invoker": "~1.1"
640
+ },
641
+ "bin": [
642
+ "phpunit"
643
+ ],
644
+ "type": "library",
645
+ "extra": {
646
+ "branch-alias": {
647
+ "dev-master": "4.8.x-dev"
648
+ }
649
+ },
650
+ "autoload": {
651
+ "classmap": [
652
+ "src/"
653
+ ]
654
+ },
655
+ "notification-url": "https://packagist.org/downloads/",
656
+ "license": [
657
+ "BSD-3-Clause"
658
+ ],
659
+ "authors": [
660
+ {
661
+ "name": "Sebastian Bergmann",
662
+ "email": "sebastian@phpunit.de",
663
+ "role": "lead"
664
+ }
665
+ ],
666
+ "description": "The PHP Unit Testing framework.",
667
+ "homepage": "https://phpunit.de/",
668
+ "keywords": [
669
+ "phpunit",
670
+ "testing",
671
+ "xunit"
672
+ ],
673
+ "time": "2016-03-14 06:16:08"
674
+ },
675
+ {
676
+ "name": "phpunit/phpunit-mock-objects",
677
+ "version": "2.3.8",
678
+ "source": {
679
+ "type": "git",
680
+ "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
681
+ "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
682
+ },
683
+ "dist": {
684
+ "type": "zip",
685
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
686
+ "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
687
+ "shasum": ""
688
+ },
689
+ "require": {
690
+ "doctrine/instantiator": "^1.0.2",
691
+ "php": ">=5.3.3",
692
+ "phpunit/php-text-template": "~1.2",
693
+ "sebastian/exporter": "~1.2"
694
+ },
695
+ "require-dev": {
696
+ "phpunit/phpunit": "~4.4"
697
+ },
698
+ "suggest": {
699
+ "ext-soap": "*"
700
+ },
701
+ "type": "library",
702
+ "extra": {
703
+ "branch-alias": {
704
+ "dev-master": "2.3.x-dev"
705
+ }
706
+ },
707
+ "autoload": {
708
+ "classmap": [
709
+ "src/"
710
+ ]
711
+ },
712
+ "notification-url": "https://packagist.org/downloads/",
713
+ "license": [
714
+ "BSD-3-Clause"
715
+ ],
716
+ "authors": [
717
+ {
718
+ "name": "Sebastian Bergmann",
719
+ "email": "sb@sebastian-bergmann.de",
720
+ "role": "lead"
721
+ }
722
+ ],
723
+ "description": "Mock Object library for PHPUnit",
724
+ "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
725
+ "keywords": [
726
+ "mock",
727
+ "xunit"
728
+ ],
729
+ "time": "2015-10-02 06:51:40"
730
+ },
731
+ {
732
+ "name": "pimple/pimple",
733
+ "version": "v2.1.1",
734
+ "source": {
735
+ "type": "git",
736
+ "url": "https://github.com/silexphp/Pimple.git",
737
+ "reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76"
738
+ },
739
+ "dist": {
740
+ "type": "zip",
741
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/ea22fb2880faf7b7b0e17c9809c6fe25b071fd76",
742
+ "reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76",
743
+ "shasum": ""
744
+ },
745
+ "require": {
746
+ "php": ">=5.3.0"
747
+ },
748
+ "type": "library",
749
+ "extra": {
750
+ "branch-alias": {
751
+ "dev-master": "2.1.x-dev"
752
+ }
753
+ },
754
+ "autoload": {
755
+ "psr-0": {
756
+ "Pimple": "src/"
757
+ }
758
+ },
759
+ "notification-url": "https://packagist.org/downloads/",
760
+ "license": [
761
+ "MIT"
762
+ ],
763
+ "authors": [
764
+ {
765
+ "name": "Fabien Potencier",
766
+ "email": "fabien@symfony.com"
767
+ }
768
+ ],
769
+ "description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
770
+ "homepage": "http://pimple.sensiolabs.org",
771
+ "keywords": [
772
+ "container",
773
+ "dependency injection"
774
+ ],
775
+ "time": "2014-07-24 07:10:08"
776
+ },
777
+ {
778
+ "name": "sami/sami",
779
+ "version": "v2.0.0",
780
+ "source": {
781
+ "type": "git",
782
+ "url": "https://github.com/FriendsOfPHP/Sami.git",
783
+ "reference": "fa58b324f41aa2aefe21dac4f22d8c98965fc012"
784
+ },
785
+ "dist": {
786
+ "type": "zip",
787
+ "url": "https://api.github.com/repos/FriendsOfPHP/Sami/zipball/fa58b324f41aa2aefe21dac4f22d8c98965fc012",
788
+ "reference": "fa58b324f41aa2aefe21dac4f22d8c98965fc012",
789
+ "shasum": ""
790
+ },
791
+ "require": {
792
+ "michelf/php-markdown": "~1.3",
793
+ "nikic/php-parser": "0.9.*",
794
+ "php": ">=5.3.0",
795
+ "pimple/pimple": "2.*",
796
+ "symfony/console": "~2.1",
797
+ "symfony/filesystem": "~2.1",
798
+ "symfony/finder": "~2.1",
799
+ "symfony/process": "~2.1",
800
+ "symfony/yaml": "~2.1",
801
+ "twig/twig": "1.*"
802
+ },
803
+ "bin": [
804
+ "sami.php"
805
+ ],
806
+ "type": "application",
807
+ "extra": {
808
+ "branch-alias": {
809
+ "dev-master": "2.0-dev"
810
+ }
811
+ },
812
+ "autoload": {
813
+ "psr-0": {
814
+ "Sami": "."
815
+ }
816
+ },
817
+ "notification-url": "https://packagist.org/downloads/",
818
+ "license": [
819
+ "MIT"
820
+ ],
821
+ "authors": [
822
+ {
823
+ "name": "Fabien Potencier",
824
+ "email": "fabien@symfony.com"
825
+ }
826
+ ],
827
+ "description": "Sami, an API documentation generator",
828
+ "homepage": "http://sami.sensiolabs.org",
829
+ "keywords": [
830
+ "phpdoc"
831
+ ],
832
+ "time": "2014-06-25 12:05:18"
833
+ },
834
+ {
835
+ "name": "sebastian/comparator",
836
+ "version": "1.2.0",
837
+ "source": {
838
+ "type": "git",
839
+ "url": "https://github.com/sebastianbergmann/comparator.git",
840
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
841
+ },
842
+ "dist": {
843
+ "type": "zip",
844
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
845
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
846
+ "shasum": ""
847
+ },
848
+ "require": {
849
+ "php": ">=5.3.3",
850
+ "sebastian/diff": "~1.2",
851
+ "sebastian/exporter": "~1.2"
852
+ },
853
+ "require-dev": {
854
+ "phpunit/phpunit": "~4.4"
855
+ },
856
+ "type": "library",
857
+ "extra": {
858
+ "branch-alias": {
859
+ "dev-master": "1.2.x-dev"
860
+ }
861
+ },
862
+ "autoload": {
863
+ "classmap": [
864
+ "src/"
865
+ ]
866
+ },
867
+ "notification-url": "https://packagist.org/downloads/",
868
+ "license": [
869
+ "BSD-3-Clause"
870
+ ],
871
+ "authors": [
872
+ {
873
+ "name": "Jeff Welch",
874
+ "email": "whatthejeff@gmail.com"
875
+ },
876
+ {
877
+ "name": "Volker Dusch",
878
+ "email": "github@wallbash.com"
879
+ },
880
+ {
881
+ "name": "Bernhard Schussek",
882
+ "email": "bschussek@2bepublished.at"
883
+ },
884
+ {
885
+ "name": "Sebastian Bergmann",
886
+ "email": "sebastian@phpunit.de"
887
+ }
888
+ ],
889
+ "description": "Provides the functionality to compare PHP values for equality",
890
+ "homepage": "http://www.github.com/sebastianbergmann/comparator",
891
+ "keywords": [
892
+ "comparator",
893
+ "compare",
894
+ "equality"
895
+ ],
896
+ "time": "2015-07-26 15:48:44"
897
+ },
898
+ {
899
+ "name": "sebastian/diff",
900
+ "version": "1.4.1",
901
+ "source": {
902
+ "type": "git",
903
+ "url": "https://github.com/sebastianbergmann/diff.git",
904
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
905
+ },
906
+ "dist": {
907
+ "type": "zip",
908
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
909
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
910
+ "shasum": ""
911
+ },
912
+ "require": {
913
+ "php": ">=5.3.3"
914
+ },
915
+ "require-dev": {
916
+ "phpunit/phpunit": "~4.8"
917
+ },
918
+ "type": "library",
919
+ "extra": {
920
+ "branch-alias": {
921
+ "dev-master": "1.4-dev"
922
+ }
923
+ },
924
+ "autoload": {
925
+ "classmap": [
926
+ "src/"
927
+ ]
928
+ },
929
+ "notification-url": "https://packagist.org/downloads/",
930
+ "license": [
931
+ "BSD-3-Clause"
932
+ ],
933
+ "authors": [
934
+ {
935
+ "name": "Kore Nordmann",
936
+ "email": "mail@kore-nordmann.de"
937
+ },
938
+ {
939
+ "name": "Sebastian Bergmann",
940
+ "email": "sebastian@phpunit.de"
941
+ }
942
+ ],
943
+ "description": "Diff implementation",
944
+ "homepage": "https://github.com/sebastianbergmann/diff",
945
+ "keywords": [
946
+ "diff"
947
+ ],
948
+ "time": "2015-12-08 07:14:41"
949
+ },
950
+ {
951
+ "name": "sebastian/environment",
952
+ "version": "1.3.5",
953
+ "source": {
954
+ "type": "git",
955
+ "url": "https://github.com/sebastianbergmann/environment.git",
956
+ "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf"
957
+ },
958
+ "dist": {
959
+ "type": "zip",
960
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf",
961
+ "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf",
962
+ "shasum": ""
963
+ },
964
+ "require": {
965
+ "php": ">=5.3.3"
966
+ },
967
+ "require-dev": {
968
+ "phpunit/phpunit": "~4.4"
969
+ },
970
+ "type": "library",
971
+ "extra": {
972
+ "branch-alias": {
973
+ "dev-master": "1.3.x-dev"
974
+ }
975
+ },
976
+ "autoload": {
977
+ "classmap": [
978
+ "src/"
979
+ ]
980
+ },
981
+ "notification-url": "https://packagist.org/downloads/",
982
+ "license": [
983
+ "BSD-3-Clause"
984
+ ],
985
+ "authors": [
986
+ {
987
+ "name": "Sebastian Bergmann",
988
+ "email": "sebastian@phpunit.de"
989
+ }
990
+ ],
991
+ "description": "Provides functionality to handle HHVM/PHP environments",
992
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
993
+ "keywords": [
994
+ "Xdebug",
995
+ "environment",
996
+ "hhvm"
997
+ ],
998
+ "time": "2016-02-26 18:40:46"
999
+ },
1000
+ {
1001
+ "name": "sebastian/exporter",
1002
+ "version": "1.2.1",
1003
+ "source": {
1004
+ "type": "git",
1005
+ "url": "https://github.com/sebastianbergmann/exporter.git",
1006
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
1007
+ },
1008
+ "dist": {
1009
+ "type": "zip",
1010
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
1011
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
1012
+ "shasum": ""
1013
+ },
1014
+ "require": {
1015
+ "php": ">=5.3.3",
1016
+ "sebastian/recursion-context": "~1.0"
1017
+ },
1018
+ "require-dev": {
1019
+ "phpunit/phpunit": "~4.4"
1020
+ },
1021
+ "type": "library",
1022
+ "extra": {
1023
+ "branch-alias": {
1024
+ "dev-master": "1.2.x-dev"
1025
+ }
1026
+ },
1027
+ "autoload": {
1028
+ "classmap": [
1029
+ "src/"
1030
+ ]
1031
+ },
1032
+ "notification-url": "https://packagist.org/downloads/",
1033
+ "license": [
1034
+ "BSD-3-Clause"
1035
+ ],
1036
+ "authors": [
1037
+ {
1038
+ "name": "Jeff Welch",
1039
+ "email": "whatthejeff@gmail.com"
1040
+ },
1041
+ {
1042
+ "name": "Volker Dusch",
1043
+ "email": "github@wallbash.com"
1044
+ },
1045
+ {
1046
+ "name": "Bernhard Schussek",
1047
+ "email": "bschussek@2bepublished.at"
1048
+ },
1049
+ {
1050
+ "name": "Sebastian Bergmann",
1051
+ "email": "sebastian@phpunit.de"
1052
+ },
1053
+ {
1054
+ "name": "Adam Harvey",
1055
+ "email": "aharvey@php.net"
1056
+ }
1057
+ ],
1058
+ "description": "Provides the functionality to export PHP variables for visualization",
1059
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
1060
+ "keywords": [
1061
+ "export",
1062
+ "exporter"
1063
+ ],
1064
+ "time": "2015-06-21 07:55:53"
1065
+ },
1066
+ {
1067
+ "name": "sebastian/global-state",
1068
+ "version": "1.1.1",
1069
+ "source": {
1070
+ "type": "git",
1071
+ "url": "https://github.com/sebastianbergmann/global-state.git",
1072
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
1073
+ },
1074
+ "dist": {
1075
+ "type": "zip",
1076
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
1077
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
1078
+ "shasum": ""
1079
+ },
1080
+ "require": {
1081
+ "php": ">=5.3.3"
1082
+ },
1083
+ "require-dev": {
1084
+ "phpunit/phpunit": "~4.2"
1085
+ },
1086
+ "suggest": {
1087
+ "ext-uopz": "*"
1088
+ },
1089
+ "type": "library",
1090
+ "extra": {
1091
+ "branch-alias": {
1092
+ "dev-master": "1.0-dev"
1093
+ }
1094
+ },
1095
+ "autoload": {
1096
+ "classmap": [
1097
+ "src/"
1098
+ ]
1099
+ },
1100
+ "notification-url": "https://packagist.org/downloads/",
1101
+ "license": [
1102
+ "BSD-3-Clause"
1103
+ ],
1104
+ "authors": [
1105
+ {
1106
+ "name": "Sebastian Bergmann",
1107
+ "email": "sebastian@phpunit.de"
1108
+ }
1109
+ ],
1110
+ "description": "Snapshotting of global state",
1111
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
1112
+ "keywords": [
1113
+ "global state"
1114
+ ],
1115
+ "time": "2015-10-12 03:26:01"
1116
+ },
1117
+ {
1118
+ "name": "sebastian/recursion-context",
1119
+ "version": "1.0.2",
1120
+ "source": {
1121
+ "type": "git",
1122
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
1123
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
1124
+ },
1125
+ "dist": {
1126
+ "type": "zip",
1127
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
1128
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
1129
+ "shasum": ""
1130
+ },
1131
+ "require": {
1132
+ "php": ">=5.3.3"
1133
+ },
1134
+ "require-dev": {
1135
+ "phpunit/phpunit": "~4.4"
1136
+ },
1137
+ "type": "library",
1138
+ "extra": {
1139
+ "branch-alias": {
1140
+ "dev-master": "1.0.x-dev"
1141
+ }
1142
+ },
1143
+ "autoload": {
1144
+ "classmap": [
1145
+ "src/"
1146
+ ]
1147
+ },
1148
+ "notification-url": "https://packagist.org/downloads/",
1149
+ "license": [
1150
+ "BSD-3-Clause"
1151
+ ],
1152
+ "authors": [
1153
+ {
1154
+ "name": "Jeff Welch",
1155
+ "email": "whatthejeff@gmail.com"
1156
+ },
1157
+ {
1158
+ "name": "Sebastian Bergmann",
1159
+ "email": "sebastian@phpunit.de"
1160
+ },
1161
+ {
1162
+ "name": "Adam Harvey",
1163
+ "email": "aharvey@php.net"
1164
+ }
1165
+ ],
1166
+ "description": "Provides functionality to recursively process PHP variables",
1167
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1168
+ "time": "2015-11-11 19:50:13"
1169
+ },
1170
+ {
1171
+ "name": "sebastian/version",
1172
+ "version": "1.0.6",
1173
+ "source": {
1174
+ "type": "git",
1175
+ "url": "https://github.com/sebastianbergmann/version.git",
1176
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
1177
+ },
1178
+ "dist": {
1179
+ "type": "zip",
1180
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1181
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1182
+ "shasum": ""
1183
+ },
1184
+ "type": "library",
1185
+ "autoload": {
1186
+ "classmap": [
1187
+ "src/"
1188
+ ]
1189
+ },
1190
+ "notification-url": "https://packagist.org/downloads/",
1191
+ "license": [
1192
+ "BSD-3-Clause"
1193
+ ],
1194
+ "authors": [
1195
+ {
1196
+ "name": "Sebastian Bergmann",
1197
+ "email": "sebastian@phpunit.de",
1198
+ "role": "lead"
1199
+ }
1200
+ ],
1201
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1202
+ "homepage": "https://github.com/sebastianbergmann/version",
1203
+ "time": "2015-06-21 13:59:46"
1204
+ },
1205
+ {
1206
+ "name": "squizlabs/php_codesniffer",
1207
+ "version": "2.6.0",
1208
+ "source": {
1209
+ "type": "git",
1210
+ "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
1211
+ "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b"
1212
+ },
1213
+ "dist": {
1214
+ "type": "zip",
1215
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1bcdf03b068a530ac1962ce671dead356eeba43b",
1216
+ "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b",
1217
+ "shasum": ""
1218
+ },
1219
+ "require": {
1220
+ "ext-simplexml": "*",
1221
+ "ext-tokenizer": "*",
1222
+ "ext-xmlwriter": "*",
1223
+ "php": ">=5.1.2"
1224
+ },
1225
+ "require-dev": {
1226
+ "phpunit/phpunit": "~4.0"
1227
+ },
1228
+ "bin": [
1229
+ "scripts/phpcs",
1230
+ "scripts/phpcbf"
1231
+ ],
1232
+ "type": "library",
1233
+ "extra": {
1234
+ "branch-alias": {
1235
+ "dev-master": "2.x-dev"
1236
+ }
1237
+ },
1238
+ "autoload": {
1239
+ "classmap": [
1240
+ "CodeSniffer.php",
1241
+ "CodeSniffer/CLI.php",
1242
+ "CodeSniffer/Exception.php",
1243
+ "CodeSniffer/File.php",
1244
+ "CodeSniffer/Fixer.php",
1245
+ "CodeSniffer/Report.php",
1246
+ "CodeSniffer/Reporting.php",
1247
+ "CodeSniffer/Sniff.php",
1248
+ "CodeSniffer/Tokens.php",
1249
+ "CodeSniffer/Reports/",
1250
+ "CodeSniffer/Tokenizers/",
1251
+ "CodeSniffer/DocGenerators/",
1252
+ "CodeSniffer/Standards/AbstractPatternSniff.php",
1253
+ "CodeSniffer/Standards/AbstractScopeSniff.php",
1254
+ "CodeSniffer/Standards/AbstractVariableSniff.php",
1255
+ "CodeSniffer/Standards/IncorrectPatternException.php",
1256
+ "CodeSniffer/Standards/Generic/Sniffs/",
1257
+ "CodeSniffer/Standards/MySource/Sniffs/",
1258
+ "CodeSniffer/Standards/PEAR/Sniffs/",
1259
+ "CodeSniffer/Standards/PSR1/Sniffs/",
1260
+ "CodeSniffer/Standards/PSR2/Sniffs/",
1261
+ "CodeSniffer/Standards/Squiz/Sniffs/",
1262
+ "CodeSniffer/Standards/Zend/Sniffs/"
1263
+ ]
1264
+ },
1265
+ "notification-url": "https://packagist.org/downloads/",
1266
+ "license": [
1267
+ "BSD-3-Clause"
1268
+ ],
1269
+ "authors": [
1270
+ {
1271
+ "name": "Greg Sherwood",
1272
+ "role": "lead"
1273
+ }
1274
+ ],
1275
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
1276
+ "homepage": "http://www.squizlabs.com/php-codesniffer",
1277
+ "keywords": [
1278
+ "phpcs",
1279
+ "standards"
1280
+ ],
1281
+ "time": "2016-04-03 22:58:34"
1282
+ },
1283
+ {
1284
+ "name": "symfony/console",
1285
+ "version": "v2.8.4",
1286
+ "source": {
1287
+ "type": "git",
1288
+ "url": "https://github.com/symfony/console.git",
1289
+ "reference": "9a5aef5fc0d4eff86853d44202b02be8d5a20154"
1290
+ },
1291
+ "dist": {
1292
+ "type": "zip",
1293
+ "url": "https://api.github.com/repos/symfony/console/zipball/9a5aef5fc0d4eff86853d44202b02be8d5a20154",
1294
+ "reference": "9a5aef5fc0d4eff86853d44202b02be8d5a20154",
1295
+ "shasum": ""
1296
+ },
1297
+ "require": {
1298
+ "php": ">=5.3.9",
1299
+ "symfony/polyfill-mbstring": "~1.0"
1300
+ },
1301
+ "require-dev": {
1302
+ "psr/log": "~1.0",
1303
+ "symfony/event-dispatcher": "~2.1|~3.0.0",
1304
+ "symfony/process": "~2.1|~3.0.0"
1305
+ },
1306
+ "suggest": {
1307
+ "psr/log": "For using the console logger",
1308
+ "symfony/event-dispatcher": "",
1309
+ "symfony/process": ""
1310
+ },
1311
+ "type": "library",
1312
+ "extra": {
1313
+ "branch-alias": {
1314
+ "dev-master": "2.8-dev"
1315
+ }
1316
+ },
1317
+ "autoload": {
1318
+ "psr-4": {
1319
+ "Symfony\\Component\\Console\\": ""
1320
+ },
1321
+ "exclude-from-classmap": [
1322
+ "/Tests/"
1323
+ ]
1324
+ },
1325
+ "notification-url": "https://packagist.org/downloads/",
1326
+ "license": [
1327
+ "MIT"
1328
+ ],
1329
+ "authors": [
1330
+ {
1331
+ "name": "Fabien Potencier",
1332
+ "email": "fabien@symfony.com"
1333
+ },
1334
+ {
1335
+ "name": "Symfony Community",
1336
+ "homepage": "https://symfony.com/contributors"
1337
+ }
1338
+ ],
1339
+ "description": "Symfony Console Component",
1340
+ "homepage": "https://symfony.com",
1341
+ "time": "2016-03-17 09:19:04"
1342
+ },
1343
+ {
1344
+ "name": "symfony/filesystem",
1345
+ "version": "v2.8.4",
1346
+ "source": {
1347
+ "type": "git",
1348
+ "url": "https://github.com/symfony/filesystem.git",
1349
+ "reference": "f08ffdf229252cd2745558cb2112df43903bcae4"
1350
+ },
1351
+ "dist": {
1352
+ "type": "zip",
1353
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/f08ffdf229252cd2745558cb2112df43903bcae4",
1354
+ "reference": "f08ffdf229252cd2745558cb2112df43903bcae4",
1355
+ "shasum": ""
1356
+ },
1357
+ "require": {
1358
+ "php": ">=5.3.9"
1359
+ },
1360
+ "type": "library",
1361
+ "extra": {
1362
+ "branch-alias": {
1363
+ "dev-master": "2.8-dev"
1364
+ }
1365
+ },
1366
+ "autoload": {
1367
+ "psr-4": {
1368
+ "Symfony\\Component\\Filesystem\\": ""
1369
+ },
1370
+ "exclude-from-classmap": [
1371
+ "/Tests/"
1372
+ ]
1373
+ },
1374
+ "notification-url": "https://packagist.org/downloads/",
1375
+ "license": [
1376
+ "MIT"
1377
+ ],
1378
+ "authors": [
1379
+ {
1380
+ "name": "Fabien Potencier",
1381
+ "email": "fabien@symfony.com"
1382
+ },
1383
+ {
1384
+ "name": "Symfony Community",
1385
+ "homepage": "https://symfony.com/contributors"
1386
+ }
1387
+ ],
1388
+ "description": "Symfony Filesystem Component",
1389
+ "homepage": "https://symfony.com",
1390
+ "time": "2016-03-27 10:20:16"
1391
+ },
1392
+ {
1393
+ "name": "symfony/finder",
1394
+ "version": "v2.8.4",
1395
+ "source": {
1396
+ "type": "git",
1397
+ "url": "https://github.com/symfony/finder.git",
1398
+ "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1"
1399
+ },
1400
+ "dist": {
1401
+ "type": "zip",
1402
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ca24cf2cd4e3826f571e0067e535758e73807aa1",
1403
+ "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1",
1404
+ "shasum": ""
1405
+ },
1406
+ "require": {
1407
+ "php": ">=5.3.9"
1408
+ },
1409
+ "type": "library",
1410
+ "extra": {
1411
+ "branch-alias": {
1412
+ "dev-master": "2.8-dev"
1413
+ }
1414
+ },
1415
+ "autoload": {
1416
+ "psr-4": {
1417
+ "Symfony\\Component\\Finder\\": ""
1418
+ },
1419
+ "exclude-from-classmap": [
1420
+ "/Tests/"
1421
+ ]
1422
+ },
1423
+ "notification-url": "https://packagist.org/downloads/",
1424
+ "license": [
1425
+ "MIT"
1426
+ ],
1427
+ "authors": [
1428
+ {
1429
+ "name": "Fabien Potencier",
1430
+ "email": "fabien@symfony.com"
1431
+ },
1432
+ {
1433
+ "name": "Symfony Community",
1434
+ "homepage": "https://symfony.com/contributors"
1435
+ }
1436
+ ],
1437
+ "description": "Symfony Finder Component",
1438
+ "homepage": "https://symfony.com",
1439
+ "time": "2016-03-10 10:53:53"
1440
+ },
1441
+ {
1442
+ "name": "symfony/polyfill-mbstring",
1443
+ "version": "v1.1.1",
1444
+ "source": {
1445
+ "type": "git",
1446
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
1447
+ "reference": "1289d16209491b584839022f29257ad859b8532d"
1448
+ },
1449
+ "dist": {
1450
+ "type": "zip",
1451
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d",
1452
+ "reference": "1289d16209491b584839022f29257ad859b8532d",
1453
+ "shasum": ""
1454
+ },
1455
+ "require": {
1456
+ "php": ">=5.3.3"
1457
+ },
1458
+ "suggest": {
1459
+ "ext-mbstring": "For best performance"
1460
+ },
1461
+ "type": "library",
1462
+ "extra": {
1463
+ "branch-alias": {
1464
+ "dev-master": "1.1-dev"
1465
+ }
1466
+ },
1467
+ "autoload": {
1468
+ "psr-4": {
1469
+ "Symfony\\Polyfill\\Mbstring\\": ""
1470
+ },
1471
+ "files": [
1472
+ "bootstrap.php"
1473
+ ]
1474
+ },
1475
+ "notification-url": "https://packagist.org/downloads/",
1476
+ "license": [
1477
+ "MIT"
1478
+ ],
1479
+ "authors": [
1480
+ {
1481
+ "name": "Nicolas Grekas",
1482
+ "email": "p@tchwork.com"
1483
+ },
1484
+ {
1485
+ "name": "Symfony Community",
1486
+ "homepage": "https://symfony.com/contributors"
1487
+ }
1488
+ ],
1489
+ "description": "Symfony polyfill for the Mbstring extension",
1490
+ "homepage": "https://symfony.com",
1491
+ "keywords": [
1492
+ "compatibility",
1493
+ "mbstring",
1494
+ "polyfill",
1495
+ "portable",
1496
+ "shim"
1497
+ ],
1498
+ "time": "2016-01-20 09:13:37"
1499
+ },
1500
+ {
1501
+ "name": "symfony/process",
1502
+ "version": "v2.8.4",
1503
+ "source": {
1504
+ "type": "git",
1505
+ "url": "https://github.com/symfony/process.git",
1506
+ "reference": "fb467471952ef5cf8497c029980e556b47545333"
1507
+ },
1508
+ "dist": {
1509
+ "type": "zip",
1510
+ "url": "https://api.github.com/repos/symfony/process/zipball/fb467471952ef5cf8497c029980e556b47545333",
1511
+ "reference": "fb467471952ef5cf8497c029980e556b47545333",
1512
+ "shasum": ""
1513
+ },
1514
+ "require": {
1515
+ "php": ">=5.3.9"
1516
+ },
1517
+ "type": "library",
1518
+ "extra": {
1519
+ "branch-alias": {
1520
+ "dev-master": "2.8-dev"
1521
+ }
1522
+ },
1523
+ "autoload": {
1524
+ "psr-4": {
1525
+ "Symfony\\Component\\Process\\": ""
1526
+ },
1527
+ "exclude-from-classmap": [
1528
+ "/Tests/"
1529
+ ]
1530
+ },
1531
+ "notification-url": "https://packagist.org/downloads/",
1532
+ "license": [
1533
+ "MIT"
1534
+ ],
1535
+ "authors": [
1536
+ {
1537
+ "name": "Fabien Potencier",
1538
+ "email": "fabien@symfony.com"
1539
+ },
1540
+ {
1541
+ "name": "Symfony Community",
1542
+ "homepage": "https://symfony.com/contributors"
1543
+ }
1544
+ ],
1545
+ "description": "Symfony Process Component",
1546
+ "homepage": "https://symfony.com",
1547
+ "time": "2016-03-23 13:11:46"
1548
+ },
1549
+ {
1550
+ "name": "symfony/yaml",
1551
+ "version": "v2.8.4",
1552
+ "source": {
1553
+ "type": "git",
1554
+ "url": "https://github.com/symfony/yaml.git",
1555
+ "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb"
1556
+ },
1557
+ "dist": {
1558
+ "type": "zip",
1559
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/584e52cb8f788a887553ba82db6caacb1d6260bb",
1560
+ "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb",
1561
+ "shasum": ""
1562
+ },
1563
+ "require": {
1564
+ "php": ">=5.3.9"
1565
+ },
1566
+ "type": "library",
1567
+ "extra": {
1568
+ "branch-alias": {
1569
+ "dev-master": "2.8-dev"
1570
+ }
1571
+ },
1572
+ "autoload": {
1573
+ "psr-4": {
1574
+ "Symfony\\Component\\Yaml\\": ""
1575
+ },
1576
+ "exclude-from-classmap": [
1577
+ "/Tests/"
1578
+ ]
1579
+ },
1580
+ "notification-url": "https://packagist.org/downloads/",
1581
+ "license": [
1582
+ "MIT"
1583
+ ],
1584
+ "authors": [
1585
+ {
1586
+ "name": "Fabien Potencier",
1587
+ "email": "fabien@symfony.com"
1588
+ },
1589
+ {
1590
+ "name": "Symfony Community",
1591
+ "homepage": "https://symfony.com/contributors"
1592
+ }
1593
+ ],
1594
+ "description": "Symfony Yaml Component",
1595
+ "homepage": "https://symfony.com",
1596
+ "time": "2016-03-04 07:54:35"
1597
+ },
1598
+ {
1599
+ "name": "twig/twig",
1600
+ "version": "v1.24.0",
1601
+ "source": {
1602
+ "type": "git",
1603
+ "url": "https://github.com/twigphp/Twig.git",
1604
+ "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8"
1605
+ },
1606
+ "dist": {
1607
+ "type": "zip",
1608
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8",
1609
+ "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8",
1610
+ "shasum": ""
1611
+ },
1612
+ "require": {
1613
+ "php": ">=5.2.7"
1614
+ },
1615
+ "require-dev": {
1616
+ "symfony/debug": "~2.7",
1617
+ "symfony/phpunit-bridge": "~2.7"
1618
+ },
1619
+ "type": "library",
1620
+ "extra": {
1621
+ "branch-alias": {
1622
+ "dev-master": "1.24-dev"
1623
+ }
1624
+ },
1625
+ "autoload": {
1626
+ "psr-0": {
1627
+ "Twig_": "lib/"
1628
+ }
1629
+ },
1630
+ "notification-url": "https://packagist.org/downloads/",
1631
+ "license": [
1632
+ "BSD-3-Clause"
1633
+ ],
1634
+ "authors": [
1635
+ {
1636
+ "name": "Fabien Potencier",
1637
+ "email": "fabien@symfony.com",
1638
+ "homepage": "http://fabien.potencier.org",
1639
+ "role": "Lead Developer"
1640
+ },
1641
+ {
1642
+ "name": "Armin Ronacher",
1643
+ "email": "armin.ronacher@active-4.com",
1644
+ "role": "Project Founder"
1645
+ },
1646
+ {
1647
+ "name": "Twig Team",
1648
+ "homepage": "http://twig.sensiolabs.org/contributors",
1649
+ "role": "Contributors"
1650
+ }
1651
+ ],
1652
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
1653
+ "homepage": "http://twig.sensiolabs.org",
1654
+ "keywords": [
1655
+ "templating"
1656
+ ],
1657
+ "time": "2016-01-25 21:22:18"
1658
+ }
1659
+ ],
1660
+ "aliases": [],
1661
+ "minimum-stability": "stable",
1662
+ "stability-flags": [],
1663
+ "prefer-stable": false,
1664
+ "prefer-lowest": false,
1665
+ "platform": {
1666
+ "php": ">=5.0.0"
1667
+ },
1668
+ "platform-dev": []
1669
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of AES.
5
+ *
6
+ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
11
+ * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
12
+ * to save one include_once().
13
+ *
14
+ * If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
15
+ * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
16
+ * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
17
+ * is called, again, at which point, it'll be recalculated.
18
+ *
19
+ * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
20
+ * make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function,
21
+ * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
22
+ *
23
+ * Here's a short example of how to use this library:
24
+ * <code>
25
+ * <?php
26
+ * include 'Crypt/AES.php';
27
+ *
28
+ * $aes = new Crypt_AES();
29
+ *
30
+ * $aes->setKey('abcdefghijklmnop');
31
+ *
32
+ * $size = 10 * 1024;
33
+ * $plaintext = '';
34
+ * for ($i = 0; $i < $size; $i++) {
35
+ * $plaintext.= 'a';
36
+ * }
37
+ *
38
+ * echo $aes->decrypt($aes->encrypt($plaintext));
39
+ * ?>
40
+ * </code>
41
+ *
42
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
43
+ * of this software and associated documentation files (the "Software"), to deal
44
+ * in the Software without restriction, including without limitation the rights
45
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46
+ * copies of the Software, and to permit persons to whom the Software is
47
+ * furnished to do so, subject to the following conditions:
48
+ *
49
+ * The above copyright notice and this permission notice shall be included in
50
+ * all copies or substantial portions of the Software.
51
+ *
52
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58
+ * THE SOFTWARE.
59
+ *
60
+ * @category Crypt
61
+ * @package Crypt_AES
62
+ * @author Jim Wigginton <terrafrost@php.net>
63
+ * @copyright 2008 Jim Wigginton
64
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
65
+ * @link http://phpseclib.sourceforge.net
66
+ */
67
+
68
+ /**
69
+ * Include Crypt_Rijndael
70
+ */
71
+ if (!class_exists('Crypt_Rijndael')) {
72
+ include_once 'Rijndael.php';
73
+ }
74
+
75
+ /**#@+
76
+ * @access public
77
+ * @see self::encrypt()
78
+ * @see self::decrypt()
79
+ */
80
+ /**
81
+ * Encrypt / decrypt using the Counter mode.
82
+ *
83
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
84
+ *
85
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
86
+ */
87
+ define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
88
+ /**
89
+ * Encrypt / decrypt using the Electronic Code Book mode.
90
+ *
91
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
92
+ */
93
+ define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
94
+ /**
95
+ * Encrypt / decrypt using the Code Book Chaining mode.
96
+ *
97
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
98
+ */
99
+ define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
100
+ /**
101
+ * Encrypt / decrypt using the Cipher Feedback mode.
102
+ *
103
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
104
+ */
105
+ define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
106
+ /**
107
+ * Encrypt / decrypt using the Cipher Feedback mode.
108
+ *
109
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
110
+ */
111
+ define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
112
+ /**#@-*/
113
+
114
+ /**
115
+ * Pure-PHP implementation of AES.
116
+ *
117
+ * @package Crypt_AES
118
+ * @author Jim Wigginton <terrafrost@php.net>
119
+ * @access public
120
+ */
121
+ class Crypt_AES extends Crypt_Rijndael
122
+ {
123
+ /**
124
+ * The namespace used by the cipher for its constants.
125
+ *
126
+ * @see Crypt_Base::const_namespace
127
+ * @var string
128
+ * @access private
129
+ */
130
+ var $const_namespace = 'AES';
131
+
132
+ /**
133
+ * Dummy function
134
+ *
135
+ * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
136
+ *
137
+ * @see Crypt_Rijndael::setBlockLength()
138
+ * @access public
139
+ * @param int $length
140
+ */
141
+ function setBlockLength($length)
142
+ {
143
+ return;
144
+ }
145
+
146
+ /**
147
+ * Sets the key length
148
+ *
149
+ * Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
150
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
151
+ *
152
+ * @see Crypt_Rijndael:setKeyLength()
153
+ * @access public
154
+ * @param int $length
155
+ */
156
+ function setKeyLength($length)
157
+ {
158
+ switch ($length) {
159
+ case 160:
160
+ $length = 192;
161
+ break;
162
+ case 224:
163
+ $length = 256;
164
+ }
165
+ parent::setKeyLength($length);
166
+ }
167
+
168
+ /**
169
+ * Sets the key.
170
+ *
171
+ * Rijndael supports five different key lengths, AES only supports three.
172
+ *
173
+ * @see Crypt_Rijndael:setKey()
174
+ * @see setKeyLength()
175
+ * @access public
176
+ * @param string $key
177
+ */
178
+ function setKey($key)
179
+ {
180
+ parent::setKey($key);
181
+
182
+ if (!$this->explicit_key_length) {
183
+ $length = strlen($key);
184
+ switch (true) {
185
+ case $length <= 16:
186
+ $this->key_length = 16;
187
+ break;
188
+ case $length <= 24:
189
+ $this->key_length = 24;
190
+ break;
191
+ default:
192
+ $this->key_length = 32;
193
+ }
194
+ $this->_setEngine();
195
+ }
196
+ }
197
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php ADDED
@@ -0,0 +1,2611 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Base Class for all Crypt_* cipher classes
5
+ *
6
+ * PHP versions 4 and 5
7
+ *
8
+ * Internally for phpseclib developers:
9
+ * If you plan to add a new cipher class, please note following rules:
10
+ *
11
+ * - The new Crypt_* cipher class should extend Crypt_Base
12
+ *
13
+ * - Following methods are then required to be overridden/overloaded:
14
+ *
15
+ * - _encryptBlock()
16
+ *
17
+ * - _decryptBlock()
18
+ *
19
+ * - _setupKey()
20
+ *
21
+ * - All other methods are optional to be overridden/overloaded
22
+ *
23
+ * - Look at the source code of the current ciphers how they extend Crypt_Base
24
+ * and take one of them as a start up for the new cipher class.
25
+ *
26
+ * - Please read all the other comments/notes/hints here also for each class var/method
27
+ *
28
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
29
+ * of this software and associated documentation files (the "Software"), to deal
30
+ * in the Software without restriction, including without limitation the rights
31
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32
+ * copies of the Software, and to permit persons to whom the Software is
33
+ * furnished to do so, subject to the following conditions:
34
+ *
35
+ * The above copyright notice and this permission notice shall be included in
36
+ * all copies or substantial portions of the Software.
37
+ *
38
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
+ * THE SOFTWARE.
45
+ *
46
+ * @category Crypt
47
+ * @package Crypt_Base
48
+ * @author Jim Wigginton <terrafrost@php.net>
49
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
50
+ * @copyright 2007 Jim Wigginton
51
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
52
+ * @link http://phpseclib.sourceforge.net
53
+ */
54
+
55
+ /**#@+
56
+ * @access public
57
+ * @see self::encrypt()
58
+ * @see self::decrypt()
59
+ */
60
+ /**
61
+ * Encrypt / decrypt using the Counter mode.
62
+ *
63
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
64
+ *
65
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
66
+ */
67
+ define('CRYPT_MODE_CTR', -1);
68
+ /**
69
+ * Encrypt / decrypt using the Electronic Code Book mode.
70
+ *
71
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
72
+ */
73
+ define('CRYPT_MODE_ECB', 1);
74
+ /**
75
+ * Encrypt / decrypt using the Code Book Chaining mode.
76
+ *
77
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
78
+ */
79
+ define('CRYPT_MODE_CBC', 2);
80
+ /**
81
+ * Encrypt / decrypt using the Cipher Feedback mode.
82
+ *
83
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
84
+ */
85
+ define('CRYPT_MODE_CFB', 3);
86
+ /**
87
+ * Encrypt / decrypt using the Output Feedback mode.
88
+ *
89
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
90
+ */
91
+ define('CRYPT_MODE_OFB', 4);
92
+ /**
93
+ * Encrypt / decrypt using streaming mode.
94
+ */
95
+ define('CRYPT_MODE_STREAM', 5);
96
+ /**#@-*/
97
+
98
+ /**#@+
99
+ * @access private
100
+ * @see self::Crypt_Base()
101
+ * @internal These constants are for internal use only
102
+ */
103
+ /**
104
+ * Base value for the internal implementation $engine switch
105
+ */
106
+ define('CRYPT_ENGINE_INTERNAL', 1);
107
+ /**
108
+ * Base value for the mcrypt implementation $engine switch
109
+ */
110
+ define('CRYPT_ENGINE_MCRYPT', 2);
111
+ /**
112
+ * Base value for the OpenSSL implementation $engine switch
113
+ */
114
+ define('CRYPT_ENGINE_OPENSSL', 3);
115
+ /**#@-*/
116
+
117
+ /**
118
+ * Base Class for all Crypt_* cipher classes
119
+ *
120
+ * @package Crypt_Base
121
+ * @author Jim Wigginton <terrafrost@php.net>
122
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
123
+ * @access public
124
+ */
125
+ class Crypt_Base
126
+ {
127
+ /**
128
+ * The Encryption Mode
129
+ *
130
+ * @see self::Crypt_Base()
131
+ * @var int
132
+ * @access private
133
+ */
134
+ var $mode;
135
+
136
+ /**
137
+ * The Block Length of the block cipher
138
+ *
139
+ * @var int
140
+ * @access private
141
+ */
142
+ var $block_size = 16;
143
+
144
+ /**
145
+ * The Key
146
+ *
147
+ * @see self::setKey()
148
+ * @var string
149
+ * @access private
150
+ */
151
+ var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
152
+
153
+ /**
154
+ * The Initialization Vector
155
+ *
156
+ * @see self::setIV()
157
+ * @var string
158
+ * @access private
159
+ */
160
+ var $iv;
161
+
162
+ /**
163
+ * A "sliding" Initialization Vector
164
+ *
165
+ * @see self::enableContinuousBuffer()
166
+ * @see self::_clearBuffers()
167
+ * @var string
168
+ * @access private
169
+ */
170
+ var $encryptIV;
171
+
172
+ /**
173
+ * A "sliding" Initialization Vector
174
+ *
175
+ * @see self::enableContinuousBuffer()
176
+ * @see self::_clearBuffers()
177
+ * @var string
178
+ * @access private
179
+ */
180
+ var $decryptIV;
181
+
182
+ /**
183
+ * Continuous Buffer status
184
+ *
185
+ * @see self::enableContinuousBuffer()
186
+ * @var bool
187
+ * @access private
188
+ */
189
+ var $continuousBuffer = false;
190
+
191
+ /**
192
+ * Encryption buffer for CTR, OFB and CFB modes
193
+ *
194
+ * @see self::encrypt()
195
+ * @see self::_clearBuffers()
196
+ * @var array
197
+ * @access private
198
+ */
199
+ var $enbuffer;
200
+
201
+ /**
202
+ * Decryption buffer for CTR, OFB and CFB modes
203
+ *
204
+ * @see self::decrypt()
205
+ * @see self::_clearBuffers()
206
+ * @var array
207
+ * @access private
208
+ */
209
+ var $debuffer;
210
+
211
+ /**
212
+ * mcrypt resource for encryption
213
+ *
214
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
215
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
216
+ *
217
+ * @see self::encrypt()
218
+ * @var resource
219
+ * @access private
220
+ */
221
+ var $enmcrypt;
222
+
223
+ /**
224
+ * mcrypt resource for decryption
225
+ *
226
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
227
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
228
+ *
229
+ * @see self::decrypt()
230
+ * @var resource
231
+ * @access private
232
+ */
233
+ var $demcrypt;
234
+
235
+ /**
236
+ * Does the enmcrypt resource need to be (re)initialized?
237
+ *
238
+ * @see Crypt_Twofish::setKey()
239
+ * @see Crypt_Twofish::setIV()
240
+ * @var bool
241
+ * @access private
242
+ */
243
+ var $enchanged = true;
244
+
245
+ /**
246
+ * Does the demcrypt resource need to be (re)initialized?
247
+ *
248
+ * @see Crypt_Twofish::setKey()
249
+ * @see Crypt_Twofish::setIV()
250
+ * @var bool
251
+ * @access private
252
+ */
253
+ var $dechanged = true;
254
+
255
+ /**
256
+ * mcrypt resource for CFB mode
257
+ *
258
+ * mcrypt's CFB mode, in (and only in) buffered context,
259
+ * is broken, so phpseclib implements the CFB mode by it self,
260
+ * even when the mcrypt php extension is available.
261
+ *
262
+ * In order to do the CFB-mode work (fast) phpseclib
263
+ * use a separate ECB-mode mcrypt resource.
264
+ *
265
+ * @link http://phpseclib.sourceforge.net/cfb-demo.phps
266
+ * @see self::encrypt()
267
+ * @see self::decrypt()
268
+ * @see self::_setupMcrypt()
269
+ * @var resource
270
+ * @access private
271
+ */
272
+ var $ecb;
273
+
274
+ /**
275
+ * Optimizing value while CFB-encrypting
276
+ *
277
+ * Only relevant if $continuousBuffer enabled
278
+ * and $engine == CRYPT_ENGINE_MCRYPT
279
+ *
280
+ * It's faster to re-init $enmcrypt if
281
+ * $buffer bytes > $cfb_init_len than
282
+ * using the $ecb resource furthermore.
283
+ *
284
+ * This value depends of the chosen cipher
285
+ * and the time it would be needed for it's
286
+ * initialization [by mcrypt_generic_init()]
287
+ * which, typically, depends on the complexity
288
+ * on its internaly Key-expanding algorithm.
289
+ *
290
+ * @see self::encrypt()
291
+ * @var int
292
+ * @access private
293
+ */
294
+ var $cfb_init_len = 600;
295
+
296
+ /**
297
+ * Does internal cipher state need to be (re)initialized?
298
+ *
299
+ * @see self::setKey()
300
+ * @see self::setIV()
301
+ * @see self::disableContinuousBuffer()
302
+ * @var bool
303
+ * @access private
304
+ */
305
+ var $changed = true;
306
+
307
+ /**
308
+ * Padding status
309
+ *
310
+ * @see self::enablePadding()
311
+ * @var bool
312
+ * @access private
313
+ */
314
+ var $padding = true;
315
+
316
+ /**
317
+ * Is the mode one that is paddable?
318
+ *
319
+ * @see self::Crypt_Base()
320
+ * @var bool
321
+ * @access private
322
+ */
323
+ var $paddable = false;
324
+
325
+ /**
326
+ * Holds which crypt engine internaly should be use,
327
+ * which will be determined automatically on __construct()
328
+ *
329
+ * Currently available $engines are:
330
+ * - CRYPT_ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
331
+ * - CRYPT_ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
332
+ * - CRYPT_ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
333
+ *
334
+ * @see self::_setEngine()
335
+ * @see self::encrypt()
336
+ * @see self::decrypt()
337
+ * @var int
338
+ * @access private
339
+ */
340
+ var $engine;
341
+
342
+ /**
343
+ * Holds the preferred crypt engine
344
+ *
345
+ * @see self::_setEngine()
346
+ * @see self::setPreferredEngine()
347
+ * @var int
348
+ * @access private
349
+ */
350
+ var $preferredEngine;
351
+
352
+ /**
353
+ * The mcrypt specific name of the cipher
354
+ *
355
+ * Only used if $engine == CRYPT_ENGINE_MCRYPT
356
+ *
357
+ * @link http://www.php.net/mcrypt_module_open
358
+ * @link http://www.php.net/mcrypt_list_algorithms
359
+ * @see self::_setupMcrypt()
360
+ * @var string
361
+ * @access private
362
+ */
363
+ var $cipher_name_mcrypt;
364
+
365
+ /**
366
+ * The openssl specific name of the cipher
367
+ *
368
+ * Only used if $engine == CRYPT_ENGINE_OPENSSL
369
+ *
370
+ * @link http://www.php.net/openssl-get-cipher-methods
371
+ * @var string
372
+ * @access private
373
+ */
374
+ var $cipher_name_openssl;
375
+
376
+ /**
377
+ * The openssl specific name of the cipher in ECB mode
378
+ *
379
+ * If OpenSSL does not support the mode we're trying to use (CTR)
380
+ * it can still be emulated with ECB mode.
381
+ *
382
+ * @link http://www.php.net/openssl-get-cipher-methods
383
+ * @var string
384
+ * @access private
385
+ */
386
+ var $cipher_name_openssl_ecb;
387
+
388
+ /**
389
+ * The default salt used by setPassword()
390
+ *
391
+ * @see self::setPassword()
392
+ * @var string
393
+ * @access private
394
+ */
395
+ var $password_default_salt = 'phpseclib/salt';
396
+
397
+ /**
398
+ * The namespace used by the cipher for its constants.
399
+ *
400
+ * ie: AES.php is using CRYPT_AES_MODE_* for its constants
401
+ * so $const_namespace is AES
402
+ *
403
+ * DES.php is using CRYPT_DES_MODE_* for its constants
404
+ * so $const_namespace is DES... and so on
405
+ *
406
+ * All CRYPT_<$const_namespace>_MODE_* are aliases of
407
+ * the generic CRYPT_MODE_* constants, so both could be used
408
+ * for each cipher.
409
+ *
410
+ * Example:
411
+ * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
412
+ * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
413
+ *
414
+ * @see self::Crypt_Base()
415
+ * @var string
416
+ * @access private
417
+ */
418
+ var $const_namespace;
419
+
420
+ /**
421
+ * The name of the performance-optimized callback function
422
+ *
423
+ * Used by encrypt() / decrypt()
424
+ * only if $engine == CRYPT_ENGINE_INTERNAL
425
+ *
426
+ * @see self::encrypt()
427
+ * @see self::decrypt()
428
+ * @see self::_setupInlineCrypt()
429
+ * @see self::$use_inline_crypt
430
+ * @var Callback
431
+ * @access private
432
+ */
433
+ var $inline_crypt;
434
+
435
+ /**
436
+ * Holds whether performance-optimized $inline_crypt() can/should be used.
437
+ *
438
+ * @see self::encrypt()
439
+ * @see self::decrypt()
440
+ * @see self::inline_crypt
441
+ * @var mixed
442
+ * @access private
443
+ */
444
+ var $use_inline_crypt;
445
+
446
+ /**
447
+ * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
448
+ *
449
+ * @see self::_openssl_ctr_process()
450
+ * @var bool
451
+ * @access private
452
+ */
453
+ var $openssl_emulate_ctr = false;
454
+
455
+ /**
456
+ * Determines what options are passed to openssl_encrypt/decrypt
457
+ *
458
+ * @see self::isValidEngine()
459
+ * @var mixed
460
+ * @access private
461
+ */
462
+ var $openssl_options;
463
+
464
+ /**
465
+ * Has the key length explicitly been set or should it be derived from the key, itself?
466
+ *
467
+ * @see self::setKeyLength()
468
+ * @var bool
469
+ * @access private
470
+ */
471
+ var $explicit_key_length = false;
472
+
473
+ /**
474
+ * Don't truncate / null pad key
475
+ *
476
+ * @see self::_clearBuffers()
477
+ * @var bool
478
+ * @access private
479
+ */
480
+ var $skip_key_adjustment = false;
481
+
482
+ /**
483
+ * Default Constructor.
484
+ *
485
+ * Determines whether or not the mcrypt extension should be used.
486
+ *
487
+ * $mode could be:
488
+ *
489
+ * - CRYPT_MODE_ECB
490
+ *
491
+ * - CRYPT_MODE_CBC
492
+ *
493
+ * - CRYPT_MODE_CTR
494
+ *
495
+ * - CRYPT_MODE_CFB
496
+ *
497
+ * - CRYPT_MODE_OFB
498
+ *
499
+ * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
500
+ *
501
+ * If not explicitly set, CRYPT_MODE_CBC will be used.
502
+ *
503
+ * @param int $mode
504
+ * @access public
505
+ */
506
+ function __construct($mode = CRYPT_MODE_CBC)
507
+ {
508
+ // $mode dependent settings
509
+ switch ($mode) {
510
+ case CRYPT_MODE_ECB:
511
+ $this->paddable = true;
512
+ $this->mode = CRYPT_MODE_ECB;
513
+ break;
514
+ case CRYPT_MODE_CTR:
515
+ case CRYPT_MODE_CFB:
516
+ case CRYPT_MODE_OFB:
517
+ case CRYPT_MODE_STREAM:
518
+ $this->mode = $mode;
519
+ break;
520
+ case CRYPT_MODE_CBC:
521
+ default:
522
+ $this->paddable = true;
523
+ $this->mode = CRYPT_MODE_CBC;
524
+ }
525
+
526
+ $this->_setEngine();
527
+
528
+ // Determining whether inline crypting can be used by the cipher
529
+ if ($this->use_inline_crypt !== false && function_exists('create_function')) {
530
+ $this->use_inline_crypt = true;
531
+ }
532
+ }
533
+
534
+ /**
535
+ * PHP4 compatible Default Constructor.
536
+ *
537
+ * @see self::__construct()
538
+ * @param int $mode
539
+ * @access public
540
+ */
541
+ function Crypt_Base($mode = CRYPT_MODE_CBC)
542
+ {
543
+ $this->__construct($mode);
544
+ }
545
+
546
+ /**
547
+ * Sets the initialization vector. (optional)
548
+ *
549
+ * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed
550
+ * to be all zero's.
551
+ *
552
+ * @access public
553
+ * @param string $iv
554
+ * @internal Can be overwritten by a sub class, but does not have to be
555
+ */
556
+ function setIV($iv)
557
+ {
558
+ if ($this->mode == CRYPT_MODE_ECB) {
559
+ return;
560
+ }
561
+
562
+ $this->iv = $iv;
563
+ $this->changed = true;
564
+ }
565
+
566
+ /**
567
+ * Sets the key length.
568
+ *
569
+ * Keys with explicitly set lengths need to be treated accordingly
570
+ *
571
+ * @access public
572
+ * @param int $length
573
+ */
574
+ function setKeyLength($length)
575
+ {
576
+ $this->explicit_key_length = true;
577
+ $this->changed = true;
578
+ $this->_setEngine();
579
+ }
580
+
581
+ /**
582
+ * Returns the current key length in bits
583
+ *
584
+ * @access public
585
+ * @return int
586
+ */
587
+ function getKeyLength()
588
+ {
589
+ return $this->key_length << 3;
590
+ }
591
+
592
+ /**
593
+ * Returns the current block length in bits
594
+ *
595
+ * @access public
596
+ * @return int
597
+ */
598
+ function getBlockLength()
599
+ {
600
+ return $this->block_size << 3;
601
+ }
602
+
603
+ /**
604
+ * Sets the key.
605
+ *
606
+ * The min/max length(s) of the key depends on the cipher which is used.
607
+ * If the key not fits the length(s) of the cipher it will paded with null bytes
608
+ * up to the closest valid key length. If the key is more than max length,
609
+ * we trim the excess bits.
610
+ *
611
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
612
+ *
613
+ * @access public
614
+ * @param string $key
615
+ * @internal Could, but not must, extend by the child Crypt_* class
616
+ */
617
+ function setKey($key)
618
+ {
619
+ if (!$this->explicit_key_length) {
620
+ $this->setKeyLength(strlen($key) << 3);
621
+ $this->explicit_key_length = false;
622
+ }
623
+
624
+ $this->key = $key;
625
+ $this->changed = true;
626
+ $this->_setEngine();
627
+ }
628
+
629
+ /**
630
+ * Sets the password.
631
+ *
632
+ * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
633
+ * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
634
+ * $hash, $salt, $count, $dkLen
635
+ *
636
+ * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
637
+ *
638
+ * @see Crypt/Hash.php
639
+ * @param string $password
640
+ * @param string $method
641
+ * @return bool
642
+ * @access public
643
+ * @internal Could, but not must, extend by the child Crypt_* class
644
+ */
645
+ function setPassword($password, $method = 'pbkdf2')
646
+ {
647
+ $key = '';
648
+
649
+ switch ($method) {
650
+ default: // 'pbkdf2' or 'pbkdf1'
651
+ $func_args = func_get_args();
652
+
653
+ // Hash function
654
+ $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
655
+
656
+ // WPA and WPA2 use the SSID as the salt
657
+ $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
658
+
659
+ // RFC2898#section-4.2 uses 1,000 iterations by default
660
+ // WPA and WPA2 use 4,096.
661
+ $count = isset($func_args[4]) ? $func_args[4] : 1000;
662
+
663
+ // Keylength
664
+ if (isset($func_args[5])) {
665
+ $dkLen = $func_args[5];
666
+ } else {
667
+ $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
668
+ }
669
+
670
+ switch (true) {
671
+ case $method == 'pbkdf1':
672
+ if (!class_exists('Crypt_Hash')) {
673
+ include_once 'Crypt/Hash.php';
674
+ }
675
+ $hashObj = new Crypt_Hash();
676
+ $hashObj->setHash($hash);
677
+ if ($dkLen > $hashObj->getLength()) {
678
+ user_error('Derived key too long');
679
+ return false;
680
+ }
681
+ $t = $password . $salt;
682
+ for ($i = 0; $i < $count; ++$i) {
683
+ $t = $hashObj->hash($t);
684
+ }
685
+ $key = substr($t, 0, $dkLen);
686
+
687
+ $this->setKey(substr($key, 0, $dkLen >> 1));
688
+ $this->setIV(substr($key, $dkLen >> 1));
689
+
690
+ return true;
691
+ // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
692
+ case !function_exists('hash_pbkdf2'):
693
+ case !function_exists('hash_algos'):
694
+ case !in_array($hash, hash_algos()):
695
+ if (!class_exists('Crypt_Hash')) {
696
+ include_once 'Crypt/Hash.php';
697
+ }
698
+ $i = 1;
699
+ while (strlen($key) < $dkLen) {
700
+ $hmac = new Crypt_Hash();
701
+ $hmac->setHash($hash);
702
+ $hmac->setKey($password);
703
+ $f = $u = $hmac->hash($salt . pack('N', $i++));
704
+ for ($j = 2; $j <= $count; ++$j) {
705
+ $u = $hmac->hash($u);
706
+ $f^= $u;
707
+ }
708
+ $key.= $f;
709
+ }
710
+ $key = substr($key, 0, $dkLen);
711
+ break;
712
+ default:
713
+ $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
714
+ }
715
+ }
716
+
717
+ $this->setKey($key);
718
+
719
+ return true;
720
+ }
721
+
722
+ /**
723
+ * Encrypts a message.
724
+ *
725
+ * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
726
+ * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
727
+ * necessary are discussed in the following
728
+ * URL:
729
+ *
730
+ * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
731
+ *
732
+ * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
733
+ * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
734
+ * length.
735
+ *
736
+ * @see self::decrypt()
737
+ * @access public
738
+ * @param string $plaintext
739
+ * @return string $ciphertext
740
+ * @internal Could, but not must, extend by the child Crypt_* class
741
+ */
742
+ function encrypt($plaintext)
743
+ {
744
+ if ($this->paddable) {
745
+ $plaintext = $this->_pad($plaintext);
746
+ }
747
+
748
+ if ($this->engine === CRYPT_ENGINE_OPENSSL) {
749
+ if ($this->changed) {
750
+ $this->_clearBuffers();
751
+ $this->changed = false;
752
+ }
753
+ switch ($this->mode) {
754
+ case CRYPT_MODE_STREAM:
755
+ return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
756
+ case CRYPT_MODE_ECB:
757
+ $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
758
+ return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
759
+ case CRYPT_MODE_CBC:
760
+ $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
761
+ if (!defined('OPENSSL_RAW_DATA')) {
762
+ $result = substr($result, 0, -$this->block_size);
763
+ }
764
+ if ($this->continuousBuffer) {
765
+ $this->encryptIV = substr($result, -$this->block_size);
766
+ }
767
+ return $result;
768
+ case CRYPT_MODE_CTR:
769
+ return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
770
+ case CRYPT_MODE_CFB:
771
+ // cfb loosely routines inspired by openssl's:
772
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
773
+ $ciphertext = '';
774
+ if ($this->continuousBuffer) {
775
+ $iv = &$this->encryptIV;
776
+ $pos = &$this->enbuffer['pos'];
777
+ } else {
778
+ $iv = $this->encryptIV;
779
+ $pos = 0;
780
+ }
781
+ $len = strlen($plaintext);
782
+ $i = 0;
783
+ if ($pos) {
784
+ $orig_pos = $pos;
785
+ $max = $this->block_size - $pos;
786
+ if ($len >= $max) {
787
+ $i = $max;
788
+ $len-= $max;
789
+ $pos = 0;
790
+ } else {
791
+ $i = $len;
792
+ $pos+= $len;
793
+ $len = 0;
794
+ }
795
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
796
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
797
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
798
+ $plaintext = substr($plaintext, $i);
799
+ }
800
+
801
+ $overflow = $len % $this->block_size;
802
+
803
+ if ($overflow) {
804
+ $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
805
+ $iv = $this->_string_pop($ciphertext, $this->block_size);
806
+
807
+ $size = $len - $overflow;
808
+ $block = $iv ^ substr($plaintext, -$overflow);
809
+ $iv = substr_replace($iv, $block, 0, $overflow);
810
+ $ciphertext.= $block;
811
+ $pos = $overflow;
812
+ } elseif ($len) {
813
+ $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
814
+ $iv = substr($ciphertext, -$this->block_size);
815
+ }
816
+
817
+ return $ciphertext;
818
+ case CRYPT_MODE_OFB:
819
+ return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
820
+ }
821
+ }
822
+
823
+ if ($this->engine === CRYPT_ENGINE_MCRYPT) {
824
+ if ($this->changed) {
825
+ $this->_setupMcrypt();
826
+ $this->changed = false;
827
+ }
828
+ if ($this->enchanged) {
829
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
830
+ $this->enchanged = false;
831
+ }
832
+
833
+ // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
834
+ // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
835
+ // rewritten CFB implementation the above outputs the same thing twice.
836
+ if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
837
+ $block_size = $this->block_size;
838
+ $iv = &$this->encryptIV;
839
+ $pos = &$this->enbuffer['pos'];
840
+ $len = strlen($plaintext);
841
+ $ciphertext = '';
842
+ $i = 0;
843
+ if ($pos) {
844
+ $orig_pos = $pos;
845
+ $max = $block_size - $pos;
846
+ if ($len >= $max) {
847
+ $i = $max;
848
+ $len-= $max;
849
+ $pos = 0;
850
+ } else {
851
+ $i = $len;
852
+ $pos+= $len;
853
+ $len = 0;
854
+ }
855
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
856
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
857
+ $this->enbuffer['enmcrypt_init'] = true;
858
+ }
859
+ if ($len >= $block_size) {
860
+ if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
861
+ if ($this->enbuffer['enmcrypt_init'] === true) {
862
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
863
+ $this->enbuffer['enmcrypt_init'] = false;
864
+ }
865
+ $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
866
+ $iv = substr($ciphertext, -$block_size);
867
+ $len%= $block_size;
868
+ } else {
869
+ while ($len >= $block_size) {
870
+ $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
871
+ $ciphertext.= $iv;
872
+ $len-= $block_size;
873
+ $i+= $block_size;
874
+ }
875
+ }
876
+ }
877
+
878
+ if ($len) {
879
+ $iv = @mcrypt_generic($this->ecb, $iv);
880
+ $block = $iv ^ substr($plaintext, -$len);
881
+ $iv = substr_replace($iv, $block, 0, $len);
882
+ $ciphertext.= $block;
883
+ $pos = $len;
884
+ }
885
+
886
+ return $ciphertext;
887
+ }
888
+
889
+ $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
890
+
891
+ if (!$this->continuousBuffer) {
892
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
893
+ }
894
+
895
+ return $ciphertext;
896
+ }
897
+
898
+ if ($this->changed) {
899
+ $this->_setup();
900
+ $this->changed = false;
901
+ }
902
+ if ($this->use_inline_crypt) {
903
+ $inline = $this->inline_crypt;
904
+ return $inline('encrypt', $this, $plaintext);
905
+ }
906
+
907
+ $buffer = &$this->enbuffer;
908
+ $block_size = $this->block_size;
909
+ $ciphertext = '';
910
+ switch ($this->mode) {
911
+ case CRYPT_MODE_ECB:
912
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
913
+ $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
914
+ }
915
+ break;
916
+ case CRYPT_MODE_CBC:
917
+ $xor = $this->encryptIV;
918
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
919
+ $block = substr($plaintext, $i, $block_size);
920
+ $block = $this->_encryptBlock($block ^ $xor);
921
+ $xor = $block;
922
+ $ciphertext.= $block;
923
+ }
924
+ if ($this->continuousBuffer) {
925
+ $this->encryptIV = $xor;
926
+ }
927
+ break;
928
+ case CRYPT_MODE_CTR:
929
+ $xor = $this->encryptIV;
930
+ if (strlen($buffer['ciphertext'])) {
931
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
932
+ $block = substr($plaintext, $i, $block_size);
933
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
934
+ $buffer['ciphertext'].= $this->_encryptBlock($xor);
935
+ }
936
+ $this->_increment_str($xor);
937
+ $key = $this->_string_shift($buffer['ciphertext'], $block_size);
938
+ $ciphertext.= $block ^ $key;
939
+ }
940
+ } else {
941
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
942
+ $block = substr($plaintext, $i, $block_size);
943
+ $key = $this->_encryptBlock($xor);
944
+ $this->_increment_str($xor);
945
+ $ciphertext.= $block ^ $key;
946
+ }
947
+ }
948
+ if ($this->continuousBuffer) {
949
+ $this->encryptIV = $xor;
950
+ if ($start = strlen($plaintext) % $block_size) {
951
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
952
+ }
953
+ }
954
+ break;
955
+ case CRYPT_MODE_CFB:
956
+ // cfb loosely routines inspired by openssl's:
957
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
958
+ if ($this->continuousBuffer) {
959
+ $iv = &$this->encryptIV;
960
+ $pos = &$buffer['pos'];
961
+ } else {
962
+ $iv = $this->encryptIV;
963
+ $pos = 0;
964
+ }
965
+ $len = strlen($plaintext);
966
+ $i = 0;
967
+ if ($pos) {
968
+ $orig_pos = $pos;
969
+ $max = $block_size - $pos;
970
+ if ($len >= $max) {
971
+ $i = $max;
972
+ $len-= $max;
973
+ $pos = 0;
974
+ } else {
975
+ $i = $len;
976
+ $pos+= $len;
977
+ $len = 0;
978
+ }
979
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
980
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
981
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
982
+ }
983
+ while ($len >= $block_size) {
984
+ $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
985
+ $ciphertext.= $iv;
986
+ $len-= $block_size;
987
+ $i+= $block_size;
988
+ }
989
+ if ($len) {
990
+ $iv = $this->_encryptBlock($iv);
991
+ $block = $iv ^ substr($plaintext, $i);
992
+ $iv = substr_replace($iv, $block, 0, $len);
993
+ $ciphertext.= $block;
994
+ $pos = $len;
995
+ }
996
+ break;
997
+ case CRYPT_MODE_OFB:
998
+ $xor = $this->encryptIV;
999
+ if (strlen($buffer['xor'])) {
1000
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1001
+ $block = substr($plaintext, $i, $block_size);
1002
+ if (strlen($block) > strlen($buffer['xor'])) {
1003
+ $xor = $this->_encryptBlock($xor);
1004
+ $buffer['xor'].= $xor;
1005
+ }
1006
+ $key = $this->_string_shift($buffer['xor'], $block_size);
1007
+ $ciphertext.= $block ^ $key;
1008
+ }
1009
+ } else {
1010
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1011
+ $xor = $this->_encryptBlock($xor);
1012
+ $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
1013
+ }
1014
+ $key = $xor;
1015
+ }
1016
+ if ($this->continuousBuffer) {
1017
+ $this->encryptIV = $xor;
1018
+ if ($start = strlen($plaintext) % $block_size) {
1019
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1020
+ }
1021
+ }
1022
+ break;
1023
+ case CRYPT_MODE_STREAM:
1024
+ $ciphertext = $this->_encryptBlock($plaintext);
1025
+ break;
1026
+ }
1027
+
1028
+ return $ciphertext;
1029
+ }
1030
+
1031
+ /**
1032
+ * Decrypts a message.
1033
+ *
1034
+ * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
1035
+ * it is.
1036
+ *
1037
+ * @see self::encrypt()
1038
+ * @access public
1039
+ * @param string $ciphertext
1040
+ * @return string $plaintext
1041
+ * @internal Could, but not must, extend by the child Crypt_* class
1042
+ */
1043
+ function decrypt($ciphertext)
1044
+ {
1045
+ if ($this->paddable) {
1046
+ // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
1047
+ // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
1048
+ $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
1049
+ }
1050
+
1051
+ if ($this->engine === CRYPT_ENGINE_OPENSSL) {
1052
+ if ($this->changed) {
1053
+ $this->_clearBuffers();
1054
+ $this->changed = false;
1055
+ }
1056
+ switch ($this->mode) {
1057
+ case CRYPT_MODE_STREAM:
1058
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1059
+ break;
1060
+ case CRYPT_MODE_ECB:
1061
+ if (!defined('OPENSSL_RAW_DATA')) {
1062
+ $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
1063
+ }
1064
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1065
+ break;
1066
+ case CRYPT_MODE_CBC:
1067
+ if (!defined('OPENSSL_RAW_DATA')) {
1068
+ $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
1069
+ $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
1070
+ $offset = 2 * $this->block_size;
1071
+ } else {
1072
+ $offset = $this->block_size;
1073
+ }
1074
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
1075
+ if ($this->continuousBuffer) {
1076
+ $this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
1077
+ }
1078
+ break;
1079
+ case CRYPT_MODE_CTR:
1080
+ $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
1081
+ break;
1082
+ case CRYPT_MODE_CFB:
1083
+ // cfb loosely routines inspired by openssl's:
1084
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1085
+ $plaintext = '';
1086
+ if ($this->continuousBuffer) {
1087
+ $iv = &$this->decryptIV;
1088
+ $pos = &$this->buffer['pos'];
1089
+ } else {
1090
+ $iv = $this->decryptIV;
1091
+ $pos = 0;
1092
+ }
1093
+ $len = strlen($ciphertext);
1094
+ $i = 0;
1095
+ if ($pos) {
1096
+ $orig_pos = $pos;
1097
+ $max = $this->block_size - $pos;
1098
+ if ($len >= $max) {
1099
+ $i = $max;
1100
+ $len-= $max;
1101
+ $pos = 0;
1102
+ } else {
1103
+ $i = $len;
1104
+ $pos+= $len;
1105
+ $len = 0;
1106
+ }
1107
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
1108
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1109
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1110
+ $ciphertext = substr($ciphertext, $i);
1111
+ }
1112
+ $overflow = $len % $this->block_size;
1113
+ if ($overflow) {
1114
+ $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1115
+ if ($len - $overflow) {
1116
+ $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
1117
+ }
1118
+ $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1119
+ $plaintext.= $iv ^ substr($ciphertext, -$overflow);
1120
+ $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
1121
+ $pos = $overflow;
1122
+ } elseif ($len) {
1123
+ $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1124
+ $iv = substr($ciphertext, -$this->block_size);
1125
+ }
1126
+ break;
1127
+ case CRYPT_MODE_OFB:
1128
+ $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
1129
+ }
1130
+
1131
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1132
+ }
1133
+
1134
+ if ($this->engine === CRYPT_ENGINE_MCRYPT) {
1135
+ $block_size = $this->block_size;
1136
+ if ($this->changed) {
1137
+ $this->_setupMcrypt();
1138
+ $this->changed = false;
1139
+ }
1140
+ if ($this->dechanged) {
1141
+ @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1142
+ $this->dechanged = false;
1143
+ }
1144
+
1145
+ if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
1146
+ $iv = &$this->decryptIV;
1147
+ $pos = &$this->debuffer['pos'];
1148
+ $len = strlen($ciphertext);
1149
+ $plaintext = '';
1150
+ $i = 0;
1151
+ if ($pos) {
1152
+ $orig_pos = $pos;
1153
+ $max = $block_size - $pos;
1154
+ if ($len >= $max) {
1155
+ $i = $max;
1156
+ $len-= $max;
1157
+ $pos = 0;
1158
+ } else {
1159
+ $i = $len;
1160
+ $pos+= $len;
1161
+ $len = 0;
1162
+ }
1163
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1164
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1165
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1166
+ }
1167
+ if ($len >= $block_size) {
1168
+ $cb = substr($ciphertext, $i, $len - $len % $block_size);
1169
+ $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
1170
+ $iv = substr($cb, -$block_size);
1171
+ $len%= $block_size;
1172
+ }
1173
+ if ($len) {
1174
+ $iv = @mcrypt_generic($this->ecb, $iv);
1175
+ $plaintext.= $iv ^ substr($ciphertext, -$len);
1176
+ $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
1177
+ $pos = $len;
1178
+ }
1179
+
1180
+ return $plaintext;
1181
+ }
1182
+
1183
+ $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
1184
+
1185
+ if (!$this->continuousBuffer) {
1186
+ @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1187
+ }
1188
+
1189
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1190
+ }
1191
+
1192
+ if ($this->changed) {
1193
+ $this->_setup();
1194
+ $this->changed = false;
1195
+ }
1196
+ if ($this->use_inline_crypt) {
1197
+ $inline = $this->inline_crypt;
1198
+ return $inline('decrypt', $this, $ciphertext);
1199
+ }
1200
+
1201
+ $block_size = $this->block_size;
1202
+
1203
+ $buffer = &$this->debuffer;
1204
+ $plaintext = '';
1205
+ switch ($this->mode) {
1206
+ case CRYPT_MODE_ECB:
1207
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1208
+ $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
1209
+ }
1210
+ break;
1211
+ case CRYPT_MODE_CBC:
1212
+ $xor = $this->decryptIV;
1213
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1214
+ $block = substr($ciphertext, $i, $block_size);
1215
+ $plaintext.= $this->_decryptBlock($block) ^ $xor;
1216
+ $xor = $block;
1217
+ }
1218
+ if ($this->continuousBuffer) {
1219
+ $this->decryptIV = $xor;
1220
+ }
1221
+ break;
1222
+ case CRYPT_MODE_CTR:
1223
+ $xor = $this->decryptIV;
1224
+ if (strlen($buffer['ciphertext'])) {
1225
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1226
+ $block = substr($ciphertext, $i, $block_size);
1227
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
1228
+ $buffer['ciphertext'].= $this->_encryptBlock($xor);
1229
+ $this->_increment_str($xor);
1230
+ }
1231
+ $key = $this->_string_shift($buffer['ciphertext'], $block_size);
1232
+ $plaintext.= $block ^ $key;
1233
+ }
1234
+ } else {
1235
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1236
+ $block = substr($ciphertext, $i, $block_size);
1237
+ $key = $this->_encryptBlock($xor);
1238
+ $this->_increment_str($xor);
1239
+ $plaintext.= $block ^ $key;
1240
+ }
1241
+ }
1242
+ if ($this->continuousBuffer) {
1243
+ $this->decryptIV = $xor;
1244
+ if ($start = strlen($ciphertext) % $block_size) {
1245
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1246
+ }
1247
+ }
1248
+ break;
1249
+ case CRYPT_MODE_CFB:
1250
+ if ($this->continuousBuffer) {
1251
+ $iv = &$this->decryptIV;
1252
+ $pos = &$buffer['pos'];
1253
+ } else {
1254
+ $iv = $this->decryptIV;
1255
+ $pos = 0;
1256
+ }
1257
+ $len = strlen($ciphertext);
1258
+ $i = 0;
1259
+ if ($pos) {
1260
+ $orig_pos = $pos;
1261
+ $max = $block_size - $pos;
1262
+ if ($len >= $max) {
1263
+ $i = $max;
1264
+ $len-= $max;
1265
+ $pos = 0;
1266
+ } else {
1267
+ $i = $len;
1268
+ $pos+= $len;
1269
+ $len = 0;
1270
+ }
1271
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1272
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1273
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1274
+ }
1275
+ while ($len >= $block_size) {
1276
+ $iv = $this->_encryptBlock($iv);
1277
+ $cb = substr($ciphertext, $i, $block_size);
1278
+ $plaintext.= $iv ^ $cb;
1279
+ $iv = $cb;
1280
+ $len-= $block_size;
1281
+ $i+= $block_size;
1282
+ }
1283
+ if ($len) {
1284
+ $iv = $this->_encryptBlock($iv);
1285
+ $plaintext.= $iv ^ substr($ciphertext, $i);
1286
+ $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
1287
+ $pos = $len;
1288
+ }
1289
+ break;
1290
+ case CRYPT_MODE_OFB:
1291
+ $xor = $this->decryptIV;
1292
+ if (strlen($buffer['xor'])) {
1293
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1294
+ $block = substr($ciphertext, $i, $block_size);
1295
+ if (strlen($block) > strlen($buffer['xor'])) {
1296
+ $xor = $this->_encryptBlock($xor);
1297
+ $buffer['xor'].= $xor;
1298
+ }
1299
+ $key = $this->_string_shift($buffer['xor'], $block_size);
1300
+ $plaintext.= $block ^ $key;
1301
+ }
1302
+ } else {
1303
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1304
+ $xor = $this->_encryptBlock($xor);
1305
+ $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
1306
+ }
1307
+ $key = $xor;
1308
+ }
1309
+ if ($this->continuousBuffer) {
1310
+ $this->decryptIV = $xor;
1311
+ if ($start = strlen($ciphertext) % $block_size) {
1312
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1313
+ }
1314
+ }
1315
+ break;
1316
+ case CRYPT_MODE_STREAM:
1317
+ $plaintext = $this->_decryptBlock($ciphertext);
1318
+ break;
1319
+ }
1320
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1321
+ }
1322
+
1323
+ /**
1324
+ * OpenSSL CTR Processor
1325
+ *
1326
+ * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1327
+ * for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1328
+ * and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
1329
+ * function will emulate CTR with ECB when necessary.
1330
+ *
1331
+ * @see self::encrypt()
1332
+ * @see self::decrypt()
1333
+ * @param string $plaintext
1334
+ * @param string $encryptIV
1335
+ * @param array $buffer
1336
+ * @return string
1337
+ * @access private
1338
+ */
1339
+ function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
1340
+ {
1341
+ $ciphertext = '';
1342
+
1343
+ $block_size = $this->block_size;
1344
+ $key = $this->key;
1345
+
1346
+ if ($this->openssl_emulate_ctr) {
1347
+ $xor = $encryptIV;
1348
+ if (strlen($buffer['ciphertext'])) {
1349
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1350
+ $block = substr($plaintext, $i, $block_size);
1351
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
1352
+ $result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1353
+ $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
1354
+ $buffer['ciphertext'].= $result;
1355
+ }
1356
+ $this->_increment_str($xor);
1357
+ $otp = $this->_string_shift($buffer['ciphertext'], $block_size);
1358
+ $ciphertext.= $block ^ $otp;
1359
+ }
1360
+ } else {
1361
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1362
+ $block = substr($plaintext, $i, $block_size);
1363
+ $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1364
+ $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
1365
+ $this->_increment_str($xor);
1366
+ $ciphertext.= $block ^ $otp;
1367
+ }
1368
+ }
1369
+ if ($this->continuousBuffer) {
1370
+ $encryptIV = $xor;
1371
+ if ($start = strlen($plaintext) % $block_size) {
1372
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1373
+ }
1374
+ }
1375
+
1376
+ return $ciphertext;
1377
+ }
1378
+
1379
+ if (strlen($buffer['ciphertext'])) {
1380
+ $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
1381
+ $plaintext = substr($plaintext, strlen($ciphertext));
1382
+
1383
+ if (!strlen($plaintext)) {
1384
+ return $ciphertext;
1385
+ }
1386
+ }
1387
+
1388
+ $overflow = strlen($plaintext) % $block_size;
1389
+ if ($overflow) {
1390
+ $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
1391
+ $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1392
+ $temp = $this->_string_pop($encrypted, $block_size);
1393
+ $ciphertext.= $encrypted . ($plaintext2 ^ $temp);
1394
+ if ($this->continuousBuffer) {
1395
+ $buffer['ciphertext'] = substr($temp, $overflow);
1396
+ $encryptIV = $temp;
1397
+ }
1398
+ } elseif (!strlen($buffer['ciphertext'])) {
1399
+ $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1400
+ $temp = $this->_string_pop($ciphertext, $block_size);
1401
+ if ($this->continuousBuffer) {
1402
+ $encryptIV = $temp;
1403
+ }
1404
+ }
1405
+ if ($this->continuousBuffer) {
1406
+ if (!defined('OPENSSL_RAW_DATA')) {
1407
+ $encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1408
+ }
1409
+ $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1410
+ if ($overflow) {
1411
+ $this->_increment_str($encryptIV);
1412
+ }
1413
+ }
1414
+
1415
+ return $ciphertext;
1416
+ }
1417
+
1418
+ /**
1419
+ * OpenSSL OFB Processor
1420
+ *
1421
+ * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1422
+ * for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1423
+ * and Crypt_Base::decrypt().
1424
+ *
1425
+ * @see self::encrypt()
1426
+ * @see self::decrypt()
1427
+ * @param string $plaintext
1428
+ * @param string $encryptIV
1429
+ * @param array $buffer
1430
+ * @return string
1431
+ * @access private
1432
+ */
1433
+ function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
1434
+ {
1435
+ if (strlen($buffer['xor'])) {
1436
+ $ciphertext = $plaintext ^ $buffer['xor'];
1437
+ $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
1438
+ $plaintext = substr($plaintext, strlen($ciphertext));
1439
+ } else {
1440
+ $ciphertext = '';
1441
+ }
1442
+
1443
+ $block_size = $this->block_size;
1444
+
1445
+ $len = strlen($plaintext);
1446
+ $key = $this->key;
1447
+ $overflow = $len % $block_size;
1448
+
1449
+ if (strlen($plaintext)) {
1450
+ if ($overflow) {
1451
+ $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1452
+ $xor = $this->_string_pop($ciphertext, $block_size);
1453
+ if ($this->continuousBuffer) {
1454
+ $encryptIV = $xor;
1455
+ }
1456
+ $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
1457
+ if ($this->continuousBuffer) {
1458
+ $buffer['xor'] = $xor;
1459
+ }
1460
+ } else {
1461
+ $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1462
+ if ($this->continuousBuffer) {
1463
+ $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
1464
+ }
1465
+ }
1466
+ }
1467
+
1468
+ return $ciphertext;
1469
+ }
1470
+
1471
+ /**
1472
+ * phpseclib <-> OpenSSL Mode Mapper
1473
+ *
1474
+ * May need to be overwritten by classes extending this one in some cases
1475
+ *
1476
+ * @return int
1477
+ * @access private
1478
+ */
1479
+ function _openssl_translate_mode()
1480
+ {
1481
+ switch ($this->mode) {
1482
+ case CRYPT_MODE_ECB:
1483
+ return 'ecb';
1484
+ case CRYPT_MODE_CBC:
1485
+ return 'cbc';
1486
+ case CRYPT_MODE_CTR:
1487
+ return 'ctr';
1488
+ case CRYPT_MODE_CFB:
1489
+ return 'cfb';
1490
+ case CRYPT_MODE_OFB:
1491
+ return 'ofb';
1492
+ }
1493
+ }
1494
+
1495
+ /**
1496
+ * Pad "packets".
1497
+ *
1498
+ * Block ciphers working by encrypting between their specified [$this->]block_size at a time
1499
+ * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
1500
+ * pad the input so that it is of the proper length.
1501
+ *
1502
+ * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
1503
+ * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
1504
+ * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
1505
+ * transmitted separately)
1506
+ *
1507
+ * @see self::disablePadding()
1508
+ * @access public
1509
+ */
1510
+ function enablePadding()
1511
+ {
1512
+ $this->padding = true;
1513
+ }
1514
+
1515
+ /**
1516
+ * Do not pad packets.
1517
+ *
1518
+ * @see self::enablePadding()
1519
+ * @access public
1520
+ */
1521
+ function disablePadding()
1522
+ {
1523
+ $this->padding = false;
1524
+ }
1525
+
1526
+ /**
1527
+ * Treat consecutive "packets" as if they are a continuous buffer.
1528
+ *
1529
+ * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
1530
+ * will yield different outputs:
1531
+ *
1532
+ * <code>
1533
+ * echo $rijndael->encrypt(substr($plaintext, 0, 16));
1534
+ * echo $rijndael->encrypt(substr($plaintext, 16, 16));
1535
+ * </code>
1536
+ * <code>
1537
+ * echo $rijndael->encrypt($plaintext);
1538
+ * </code>
1539
+ *
1540
+ * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
1541
+ * another, as demonstrated with the following:
1542
+ *
1543
+ * <code>
1544
+ * $rijndael->encrypt(substr($plaintext, 0, 16));
1545
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1546
+ * </code>
1547
+ * <code>
1548
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1549
+ * </code>
1550
+ *
1551
+ * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
1552
+ * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
1553
+ * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
1554
+ *
1555
+ * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
1556
+ * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
1557
+ * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
1558
+ * however, they are also less intuitive and more likely to cause you problems.
1559
+ *
1560
+ * @see self::disableContinuousBuffer()
1561
+ * @access public
1562
+ * @internal Could, but not must, extend by the child Crypt_* class
1563
+ */
1564
+ function enableContinuousBuffer()
1565
+ {
1566
+ if ($this->mode == CRYPT_MODE_ECB) {
1567
+ return;
1568
+ }
1569
+
1570
+ $this->continuousBuffer = true;
1571
+
1572
+ $this->_setEngine();
1573
+ }
1574
+
1575
+ /**
1576
+ * Treat consecutive packets as if they are a discontinuous buffer.
1577
+ *
1578
+ * The default behavior.
1579
+ *
1580
+ * @see self::enableContinuousBuffer()
1581
+ * @access public
1582
+ * @internal Could, but not must, extend by the child Crypt_* class
1583
+ */
1584
+ function disableContinuousBuffer()
1585
+ {
1586
+ if ($this->mode == CRYPT_MODE_ECB) {
1587
+ return;
1588
+ }
1589
+ if (!$this->continuousBuffer) {
1590
+ return;
1591
+ }
1592
+
1593
+ $this->continuousBuffer = false;
1594
+ $this->changed = true;
1595
+
1596
+ $this->_setEngine();
1597
+ }
1598
+
1599
+ /**
1600
+ * Test for engine validity
1601
+ *
1602
+ * @see self::Crypt_Base()
1603
+ * @param int $engine
1604
+ * @access public
1605
+ * @return bool
1606
+ */
1607
+ function isValidEngine($engine)
1608
+ {
1609
+ switch ($engine) {
1610
+ case CRYPT_ENGINE_OPENSSL:
1611
+ if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) {
1612
+ return false;
1613
+ }
1614
+ $this->openssl_emulate_ctr = false;
1615
+ $result = $this->cipher_name_openssl &&
1616
+ extension_loaded('openssl') &&
1617
+ // PHP 5.3.0 - 5.3.2 did not let you set IV's
1618
+ version_compare(PHP_VERSION, '5.3.3', '>=');
1619
+ if (!$result) {
1620
+ return false;
1621
+ }
1622
+
1623
+ // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
1624
+ // $options openssl_encrypt expected a boolean $raw_data.
1625
+ if (!defined('OPENSSL_RAW_DATA')) {
1626
+ $this->openssl_options = true;
1627
+ } else {
1628
+ $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
1629
+ }
1630
+
1631
+ $methods = openssl_get_cipher_methods();
1632
+ if (in_array($this->cipher_name_openssl, $methods)) {
1633
+ return true;
1634
+ }
1635
+ // not all of openssl's symmetric cipher's support ctr. for those
1636
+ // that don't we'll emulate it
1637
+ switch ($this->mode) {
1638
+ case CRYPT_MODE_CTR:
1639
+ if (in_array($this->cipher_name_openssl_ecb, $methods)) {
1640
+ $this->openssl_emulate_ctr = true;
1641
+ return true;
1642
+ }
1643
+ }
1644
+ return false;
1645
+ case CRYPT_ENGINE_MCRYPT:
1646
+ return $this->cipher_name_mcrypt &&
1647
+ extension_loaded('mcrypt') &&
1648
+ in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
1649
+ case CRYPT_ENGINE_INTERNAL:
1650
+ return true;
1651
+ }
1652
+
1653
+ return false;
1654
+ }
1655
+
1656
+ /**
1657
+ * Sets the preferred crypt engine
1658
+ *
1659
+ * Currently, $engine could be:
1660
+ *
1661
+ * - CRYPT_ENGINE_OPENSSL [very fast]
1662
+ *
1663
+ * - CRYPT_ENGINE_MCRYPT [fast]
1664
+ *
1665
+ * - CRYPT_ENGINE_INTERNAL [slow]
1666
+ *
1667
+ * If the preferred crypt engine is not available the fastest available one will be used
1668
+ *
1669
+ * @see self::Crypt_Base()
1670
+ * @param int $engine
1671
+ * @access public
1672
+ */
1673
+ function setPreferredEngine($engine)
1674
+ {
1675
+ switch ($engine) {
1676
+ //case CRYPT_ENGINE_OPENSSL:
1677
+ case CRYPT_ENGINE_MCRYPT:
1678
+ case CRYPT_ENGINE_INTERNAL:
1679
+ $this->preferredEngine = $engine;
1680
+ break;
1681
+ default:
1682
+ $this->preferredEngine = CRYPT_ENGINE_OPENSSL;
1683
+ }
1684
+
1685
+ $this->_setEngine();
1686
+ }
1687
+
1688
+ /**
1689
+ * Returns the engine currently being utilized
1690
+ *
1691
+ * @see self::_setEngine()
1692
+ * @access public
1693
+ */
1694
+ function getEngine()
1695
+ {
1696
+ return $this->engine;
1697
+ }
1698
+
1699
+ /**
1700
+ * Sets the engine as appropriate
1701
+ *
1702
+ * @see self::Crypt_Base()
1703
+ * @access private
1704
+ */
1705
+ function _setEngine()
1706
+ {
1707
+ $this->engine = null;
1708
+
1709
+ $candidateEngines = array(
1710
+ $this->preferredEngine,
1711
+ CRYPT_ENGINE_OPENSSL,
1712
+ CRYPT_ENGINE_MCRYPT
1713
+ );
1714
+ foreach ($candidateEngines as $engine) {
1715
+ if ($this->isValidEngine($engine)) {
1716
+ $this->engine = $engine;
1717
+ break;
1718
+ }
1719
+ }
1720
+ if (!$this->engine) {
1721
+ $this->engine = CRYPT_ENGINE_INTERNAL;
1722
+ }
1723
+
1724
+ if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) {
1725
+ // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
1726
+ // (re)open them with the module named in $this->cipher_name_mcrypt
1727
+ @mcrypt_module_close($this->enmcrypt);
1728
+ @mcrypt_module_close($this->demcrypt);
1729
+ $this->enmcrypt = null;
1730
+ $this->demcrypt = null;
1731
+
1732
+ if ($this->ecb) {
1733
+ @mcrypt_module_close($this->ecb);
1734
+ $this->ecb = null;
1735
+ }
1736
+ }
1737
+
1738
+ $this->changed = true;
1739
+ }
1740
+
1741
+ /**
1742
+ * Encrypts a block
1743
+ *
1744
+ * @access private
1745
+ * @param string $in
1746
+ * @return string
1747
+ * @internal Must be extended by the child Crypt_* class
1748
+ */
1749
+ function _encryptBlock($in)
1750
+ {
1751
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1752
+ }
1753
+
1754
+ /**
1755
+ * Decrypts a block
1756
+ *
1757
+ * @access private
1758
+ * @param string $in
1759
+ * @return string
1760
+ * @internal Must be extended by the child Crypt_* class
1761
+ */
1762
+ function _decryptBlock($in)
1763
+ {
1764
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1765
+ }
1766
+
1767
+ /**
1768
+ * Setup the key (expansion)
1769
+ *
1770
+ * Only used if $engine == CRYPT_ENGINE_INTERNAL
1771
+ *
1772
+ * @see self::_setup()
1773
+ * @access private
1774
+ * @internal Must be extended by the child Crypt_* class
1775
+ */
1776
+ function _setupKey()
1777
+ {
1778
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1779
+ }
1780
+
1781
+ /**
1782
+ * Setup the CRYPT_ENGINE_INTERNAL $engine
1783
+ *
1784
+ * (re)init, if necessary, the internal cipher $engine and flush all $buffers
1785
+ * Used (only) if $engine == CRYPT_ENGINE_INTERNAL
1786
+ *
1787
+ * _setup() will be called each time if $changed === true
1788
+ * typically this happens when using one or more of following public methods:
1789
+ *
1790
+ * - setKey()
1791
+ *
1792
+ * - setIV()
1793
+ *
1794
+ * - disableContinuousBuffer()
1795
+ *
1796
+ * - First run of encrypt() / decrypt() with no init-settings
1797
+ *
1798
+ * @see self::setKey()
1799
+ * @see self::setIV()
1800
+ * @see self::disableContinuousBuffer()
1801
+ * @access private
1802
+ * @internal _setup() is always called before en/decryption.
1803
+ * @internal Could, but not must, extend by the child Crypt_* class
1804
+ */
1805
+ function _setup()
1806
+ {
1807
+ $this->_clearBuffers();
1808
+ $this->_setupKey();
1809
+
1810
+ if ($this->use_inline_crypt) {
1811
+ $this->_setupInlineCrypt();
1812
+ }
1813
+ }
1814
+
1815
+ /**
1816
+ * Setup the CRYPT_ENGINE_MCRYPT $engine
1817
+ *
1818
+ * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
1819
+ * Used (only) if $engine = CRYPT_ENGINE_MCRYPT
1820
+ *
1821
+ * _setupMcrypt() will be called each time if $changed === true
1822
+ * typically this happens when using one or more of following public methods:
1823
+ *
1824
+ * - setKey()
1825
+ *
1826
+ * - setIV()
1827
+ *
1828
+ * - disableContinuousBuffer()
1829
+ *
1830
+ * - First run of encrypt() / decrypt()
1831
+ *
1832
+ * @see self::setKey()
1833
+ * @see self::setIV()
1834
+ * @see self::disableContinuousBuffer()
1835
+ * @access private
1836
+ * @internal Could, but not must, extend by the child Crypt_* class
1837
+ */
1838
+ function _setupMcrypt()
1839
+ {
1840
+ $this->_clearBuffers();
1841
+ $this->enchanged = $this->dechanged = true;
1842
+
1843
+ if (!isset($this->enmcrypt)) {
1844
+ static $mcrypt_modes = array(
1845
+ CRYPT_MODE_CTR => 'ctr',
1846
+ CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
1847
+ CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
1848
+ CRYPT_MODE_CFB => 'ncfb',
1849
+ CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
1850
+ CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
1851
+ );
1852
+
1853
+ $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1854
+ $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1855
+
1856
+ // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
1857
+ // to workaround mcrypt's broken ncfb implementation in buffered mode
1858
+ // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
1859
+ if ($this->mode == CRYPT_MODE_CFB) {
1860
+ $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
1861
+ }
1862
+ } // else should mcrypt_generic_deinit be called?
1863
+
1864
+ if ($this->mode == CRYPT_MODE_CFB) {
1865
+ @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
1866
+ }
1867
+ }
1868
+
1869
+ /**
1870
+ * Pads a string
1871
+ *
1872
+ * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
1873
+ * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
1874
+ * chr($this->block_size - (strlen($text) % $this->block_size)
1875
+ *
1876
+ * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
1877
+ * and padding will, hence forth, be enabled.
1878
+ *
1879
+ * @see self::_unpad()
1880
+ * @param string $text
1881
+ * @access private
1882
+ * @return string
1883
+ */
1884
+ function _pad($text)
1885
+ {
1886
+ $length = strlen($text);
1887
+
1888
+ if (!$this->padding) {
1889
+ if ($length % $this->block_size == 0) {
1890
+ return $text;
1891
+ } else {
1892
+ user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
1893
+ $this->padding = true;
1894
+ }
1895
+ }
1896
+
1897
+ $pad = $this->block_size - ($length % $this->block_size);
1898
+
1899
+ return str_pad($text, $length + $pad, chr($pad));
1900
+ }
1901
+
1902
+ /**
1903
+ * Unpads a string.
1904
+ *
1905
+ * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
1906
+ * and false will be returned.
1907
+ *
1908
+ * @see self::_pad()
1909
+ * @param string $text
1910
+ * @access private
1911
+ * @return string
1912
+ */
1913
+ function _unpad($text)
1914
+ {
1915
+ if (!$this->padding) {
1916
+ return $text;
1917
+ }
1918
+
1919
+ $length = ord($text[strlen($text) - 1]);
1920
+
1921
+ if (!$length || $length > $this->block_size) {
1922
+ return false;
1923
+ }
1924
+
1925
+ return substr($text, 0, -$length);
1926
+ }
1927
+
1928
+ /**
1929
+ * Clears internal buffers
1930
+ *
1931
+ * Clearing/resetting the internal buffers is done everytime
1932
+ * after disableContinuousBuffer() or on cipher $engine (re)init
1933
+ * ie after setKey() or setIV()
1934
+ *
1935
+ * @access public
1936
+ * @internal Could, but not must, extend by the child Crypt_* class
1937
+ */
1938
+ function _clearBuffers()
1939
+ {
1940
+ $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
1941
+
1942
+ // mcrypt's handling of invalid's $iv:
1943
+ // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
1944
+ $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
1945
+
1946
+ if (!$this->skip_key_adjustment) {
1947
+ $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
1948
+ }
1949
+ }
1950
+
1951
+ /**
1952
+ * String Shift
1953
+ *
1954
+ * Inspired by array_shift
1955
+ *
1956
+ * @param string $string
1957
+ * @param int $index
1958
+ * @access private
1959
+ * @return string
1960
+ */
1961
+ function _string_shift(&$string, $index = 1)
1962
+ {
1963
+ $substr = substr($string, 0, $index);
1964
+ $string = substr($string, $index);
1965
+ return $substr;
1966
+ }
1967
+
1968
+ /**
1969
+ * String Pop
1970
+ *
1971
+ * Inspired by array_pop
1972
+ *
1973
+ * @param string $string
1974
+ * @param int $index
1975
+ * @access private
1976
+ * @return string
1977
+ */
1978
+ function _string_pop(&$string, $index = 1)
1979
+ {
1980
+ $substr = substr($string, -$index);
1981
+ $string = substr($string, 0, -$index);
1982
+ return $substr;
1983
+ }
1984
+
1985
+ /**
1986
+ * Increment the current string
1987
+ *
1988
+ * @see self::decrypt()
1989
+ * @see self::encrypt()
1990
+ * @param string $var
1991
+ * @access private
1992
+ */
1993
+ function _increment_str(&$var)
1994
+ {
1995
+ for ($i = 4; $i <= strlen($var); $i+= 4) {
1996
+ $temp = substr($var, -$i, 4);
1997
+ switch ($temp) {
1998
+ case "\xFF\xFF\xFF\xFF":
1999
+ $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
2000
+ break;
2001
+ case "\x7F\xFF\xFF\xFF":
2002
+ $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
2003
+ return;
2004
+ default:
2005
+ $temp = unpack('Nnum', $temp);
2006
+ $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
2007
+ return;
2008
+ }
2009
+ }
2010
+
2011
+ $remainder = strlen($var) % 4;
2012
+
2013
+ if ($remainder == 0) {
2014
+ return;
2015
+ }
2016
+
2017
+ $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
2018
+ $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
2019
+ $var = substr_replace($var, $temp, 0, $remainder);
2020
+ }
2021
+
2022
+ /**
2023
+ * Setup the performance-optimized function for de/encrypt()
2024
+ *
2025
+ * Stores the created (or existing) callback function-name
2026
+ * in $this->inline_crypt
2027
+ *
2028
+ * Internally for phpseclib developers:
2029
+ *
2030
+ * _setupInlineCrypt() would be called only if:
2031
+ *
2032
+ * - $engine == CRYPT_ENGINE_INTERNAL and
2033
+ *
2034
+ * - $use_inline_crypt === true
2035
+ *
2036
+ * - each time on _setup(), after(!) _setupKey()
2037
+ *
2038
+ *
2039
+ * This ensures that _setupInlineCrypt() has always a
2040
+ * full ready2go initializated internal cipher $engine state
2041
+ * where, for example, the keys allready expanded,
2042
+ * keys/block_size calculated and such.
2043
+ *
2044
+ * It is, each time if called, the responsibility of _setupInlineCrypt():
2045
+ *
2046
+ * - to set $this->inline_crypt to a valid and fully working callback function
2047
+ * as a (faster) replacement for encrypt() / decrypt()
2048
+ *
2049
+ * - NOT to create unlimited callback functions (for memory reasons!)
2050
+ * no matter how often _setupInlineCrypt() would be called. At some
2051
+ * point of amount they must be generic re-useable.
2052
+ *
2053
+ * - the code of _setupInlineCrypt() it self,
2054
+ * and the generated callback code,
2055
+ * must be, in following order:
2056
+ * - 100% safe
2057
+ * - 100% compatible to encrypt()/decrypt()
2058
+ * - using only php5+ features/lang-constructs/php-extensions if
2059
+ * compatibility (down to php4) or fallback is provided
2060
+ * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
2061
+ * - >= 10% faster than encrypt()/decrypt() [which is, by the way,
2062
+ * the reason for the existence of _setupInlineCrypt() :-)]
2063
+ * - memory-nice
2064
+ * - short (as good as possible)
2065
+ *
2066
+ * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
2067
+ * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
2068
+ * - The following variable names are reserved:
2069
+ * - $_* (all variable names prefixed with an underscore)
2070
+ * - $self (object reference to it self. Do not use $this, but $self instead)
2071
+ * - $in (the content of $in has to en/decrypt by the generated code)
2072
+ * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
2073
+ *
2074
+ *
2075
+ * @see self::_setup()
2076
+ * @see self::_createInlineCryptFunction()
2077
+ * @see self::encrypt()
2078
+ * @see self::decrypt()
2079
+ * @access private
2080
+ * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
2081
+ */
2082
+ function _setupInlineCrypt()
2083
+ {
2084
+ // If, for any reason, an extending Crypt_Base() Crypt_* class
2085
+ // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
2086
+ // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
2087
+ // in the constructor at object instance-time
2088
+ // or, if it's runtime-specific, at runtime
2089
+
2090
+ $this->use_inline_crypt = false;
2091
+ }
2092
+
2093
+ /**
2094
+ * Creates the performance-optimized function for en/decrypt()
2095
+ *
2096
+ * Internally for phpseclib developers:
2097
+ *
2098
+ * _createInlineCryptFunction():
2099
+ *
2100
+ * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
2101
+ * with the current [$this->]mode of operation code
2102
+ *
2103
+ * - create the $inline function, which called by encrypt() / decrypt()
2104
+ * as its replacement to speed up the en/decryption operations.
2105
+ *
2106
+ * - return the name of the created $inline callback function
2107
+ *
2108
+ * - used to speed up en/decryption
2109
+ *
2110
+ *
2111
+ *
2112
+ * The main reason why can speed up things [up to 50%] this way are:
2113
+ *
2114
+ * - using variables more effective then regular.
2115
+ * (ie no use of expensive arrays but integers $k_0, $k_1 ...
2116
+ * or even, for example, the pure $key[] values hardcoded)
2117
+ *
2118
+ * - avoiding 1000's of function calls of ie _encryptBlock()
2119
+ * but inlining the crypt operations.
2120
+ * in the mode of operation for() loop.
2121
+ *
2122
+ * - full loop unroll the (sometimes key-dependent) rounds
2123
+ * avoiding this way ++$i counters and runtime-if's etc...
2124
+ *
2125
+ * The basic code architectur of the generated $inline en/decrypt()
2126
+ * lambda function, in pseudo php, is:
2127
+ *
2128
+ * <code>
2129
+ * +----------------------------------------------------------------------------------------------+
2130
+ * | callback $inline = create_function: |
2131
+ * | lambda_function_0001_crypt_ECB($action, $text) |
2132
+ * | { |
2133
+ * | INSERT PHP CODE OF: |
2134
+ * | $cipher_code['init_crypt']; // general init code. |
2135
+ * | // ie: $sbox'es declarations used for |
2136
+ * | // encrypt and decrypt'ing. |
2137
+ * | |
2138
+ * | switch ($action) { |
2139
+ * | case 'encrypt': |
2140
+ * | INSERT PHP CODE OF: |
2141
+ * | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
2142
+ * | ie: specified $key or $box |
2143
+ * | declarations for encrypt'ing. |
2144
+ * | |
2145
+ * | foreach ($ciphertext) { |
2146
+ * | $in = $block_size of $ciphertext; |
2147
+ * | |
2148
+ * | INSERT PHP CODE OF: |
2149
+ * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
2150
+ * | // strlen($in) == $this->block_size |
2151
+ * | // here comes the cipher algorithm in action |
2152
+ * | // for encryption. |
2153
+ * | // $cipher_code['encrypt_block'] has to |
2154
+ * | // encrypt the content of the $in variable |
2155
+ * | |
2156
+ * | $plaintext .= $in; |
2157
+ * | } |
2158
+ * | return $plaintext; |
2159
+ * | |
2160
+ * | case 'decrypt': |
2161
+ * | INSERT PHP CODE OF: |
2162
+ * | $cipher_code['init_decrypt']; // decrypt sepcific init code |
2163
+ * | ie: specified $key or $box |
2164
+ * | declarations for decrypt'ing. |
2165
+ * | foreach ($plaintext) { |
2166
+ * | $in = $block_size of $plaintext; |
2167
+ * | |
2168
+ * | INSERT PHP CODE OF: |
2169
+ * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
2170
+ * | // strlen($in) == $this->block_size |
2171
+ * | // here comes the cipher algorithm in action |
2172
+ * | // for decryption. |
2173
+ * | // $cipher_code['decrypt_block'] has to |
2174
+ * | // decrypt the content of the $in variable |
2175
+ * | $ciphertext .= $in; |
2176
+ * | } |
2177
+ * | return $ciphertext; |
2178
+ * | } |
2179
+ * | } |
2180
+ * +----------------------------------------------------------------------------------------------+
2181
+ * </code>
2182
+ *
2183
+ * See also the Crypt_*::_setupInlineCrypt()'s for
2184
+ * productive inline $cipher_code's how they works.
2185
+ *
2186
+ * Structure of:
2187
+ * <code>
2188
+ * $cipher_code = array(
2189
+ * 'init_crypt' => (string) '', // optional
2190
+ * 'init_encrypt' => (string) '', // optional
2191
+ * 'init_decrypt' => (string) '', // optional
2192
+ * 'encrypt_block' => (string) '', // required
2193
+ * 'decrypt_block' => (string) '' // required
2194
+ * );
2195
+ * </code>
2196
+ *
2197
+ * @see self::_setupInlineCrypt()
2198
+ * @see self::encrypt()
2199
+ * @see self::decrypt()
2200
+ * @param array $cipher_code
2201
+ * @access private
2202
+ * @return string (the name of the created callback function)
2203
+ */
2204
+ function _createInlineCryptFunction($cipher_code)
2205
+ {
2206
+ $block_size = $this->block_size;
2207
+
2208
+ // optional
2209
+ $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
2210
+ $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
2211
+ $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
2212
+ // required
2213
+ $encrypt_block = $cipher_code['encrypt_block'];
2214
+ $decrypt_block = $cipher_code['decrypt_block'];
2215
+
2216
+ // Generating mode of operation inline code,
2217
+ // merged with the $cipher_code algorithm
2218
+ // for encrypt- and decryption.
2219
+ switch ($this->mode) {
2220
+ case CRYPT_MODE_ECB:
2221
+ $encrypt = $init_encrypt . '
2222
+ $_ciphertext = "";
2223
+ $_plaintext_len = strlen($_text);
2224
+
2225
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2226
+ $in = substr($_text, $_i, '.$block_size.');
2227
+ '.$encrypt_block.'
2228
+ $_ciphertext.= $in;
2229
+ }
2230
+
2231
+ return $_ciphertext;
2232
+ ';
2233
+
2234
+ $decrypt = $init_decrypt . '
2235
+ $_plaintext = "";
2236
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2237
+ $_ciphertext_len = strlen($_text);
2238
+
2239
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2240
+ $in = substr($_text, $_i, '.$block_size.');
2241
+ '.$decrypt_block.'
2242
+ $_plaintext.= $in;
2243
+ }
2244
+
2245
+ return $self->_unpad($_plaintext);
2246
+ ';
2247
+ break;
2248
+ case CRYPT_MODE_CTR:
2249
+ $encrypt = $init_encrypt . '
2250
+ $_ciphertext = "";
2251
+ $_plaintext_len = strlen($_text);
2252
+ $_xor = $self->encryptIV;
2253
+ $_buffer = &$self->enbuffer;
2254
+ if (strlen($_buffer["ciphertext"])) {
2255
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2256
+ $_block = substr($_text, $_i, '.$block_size.');
2257
+ if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2258
+ $in = $_xor;
2259
+ '.$encrypt_block.'
2260
+ $self->_increment_str($_xor);
2261
+ $_buffer["ciphertext"].= $in;
2262
+ }
2263
+ $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2264
+ $_ciphertext.= $_block ^ $_key;
2265
+ }
2266
+ } else {
2267
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2268
+ $_block = substr($_text, $_i, '.$block_size.');
2269
+ $in = $_xor;
2270
+ '.$encrypt_block.'
2271
+ $self->_increment_str($_xor);
2272
+ $_key = $in;
2273
+ $_ciphertext.= $_block ^ $_key;
2274
+ }
2275
+ }
2276
+ if ($self->continuousBuffer) {
2277
+ $self->encryptIV = $_xor;
2278
+ if ($_start = $_plaintext_len % '.$block_size.') {
2279
+ $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2280
+ }
2281
+ }
2282
+
2283
+ return $_ciphertext;
2284
+ ';
2285
+
2286
+ $decrypt = $init_encrypt . '
2287
+ $_plaintext = "";
2288
+ $_ciphertext_len = strlen($_text);
2289
+ $_xor = $self->decryptIV;
2290
+ $_buffer = &$self->debuffer;
2291
+
2292
+ if (strlen($_buffer["ciphertext"])) {
2293
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2294
+ $_block = substr($_text, $_i, '.$block_size.');
2295
+ if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2296
+ $in = $_xor;
2297
+ '.$encrypt_block.'
2298
+ $self->_increment_str($_xor);
2299
+ $_buffer["ciphertext"].= $in;
2300
+ }
2301
+ $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2302
+ $_plaintext.= $_block ^ $_key;
2303
+ }
2304
+ } else {
2305
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2306
+ $_block = substr($_text, $_i, '.$block_size.');
2307
+ $in = $_xor;
2308
+ '.$encrypt_block.'
2309
+ $self->_increment_str($_xor);
2310
+ $_key = $in;
2311
+ $_plaintext.= $_block ^ $_key;
2312
+ }
2313
+ }
2314
+ if ($self->continuousBuffer) {
2315
+ $self->decryptIV = $_xor;
2316
+ if ($_start = $_ciphertext_len % '.$block_size.') {
2317
+ $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2318
+ }
2319
+ }
2320
+
2321
+ return $_plaintext;
2322
+ ';
2323
+ break;
2324
+ case CRYPT_MODE_CFB:
2325
+ $encrypt = $init_encrypt . '
2326
+ $_ciphertext = "";
2327
+ $_buffer = &$self->enbuffer;
2328
+
2329
+ if ($self->continuousBuffer) {
2330
+ $_iv = &$self->encryptIV;
2331
+ $_pos = &$_buffer["pos"];
2332
+ } else {
2333
+ $_iv = $self->encryptIV;
2334
+ $_pos = 0;
2335
+ }
2336
+ $_len = strlen($_text);
2337
+ $_i = 0;
2338
+ if ($_pos) {
2339
+ $_orig_pos = $_pos;
2340
+ $_max = '.$block_size.' - $_pos;
2341
+ if ($_len >= $_max) {
2342
+ $_i = $_max;
2343
+ $_len-= $_max;
2344
+ $_pos = 0;
2345
+ } else {
2346
+ $_i = $_len;
2347
+ $_pos+= $_len;
2348
+ $_len = 0;
2349
+ }
2350
+ $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
2351
+ $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
2352
+ }
2353
+ while ($_len >= '.$block_size.') {
2354
+ $in = $_iv;
2355
+ '.$encrypt_block.';
2356
+ $_iv = $in ^ substr($_text, $_i, '.$block_size.');
2357
+ $_ciphertext.= $_iv;
2358
+ $_len-= '.$block_size.';
2359
+ $_i+= '.$block_size.';
2360
+ }
2361
+ if ($_len) {
2362
+ $in = $_iv;
2363
+ '.$encrypt_block.'
2364
+ $_iv = $in;
2365
+ $_block = $_iv ^ substr($_text, $_i);
2366
+ $_iv = substr_replace($_iv, $_block, 0, $_len);
2367
+ $_ciphertext.= $_block;
2368
+ $_pos = $_len;
2369
+ }
2370
+ return $_ciphertext;
2371
+ ';
2372
+
2373
+ $decrypt = $init_encrypt . '
2374
+ $_plaintext = "";
2375
+ $_buffer = &$self->debuffer;
2376
+
2377
+ if ($self->continuousBuffer) {
2378
+ $_iv = &$self->decryptIV;
2379
+ $_pos = &$_buffer["pos"];
2380
+ } else {
2381
+ $_iv = $self->decryptIV;
2382
+ $_pos = 0;
2383
+ }
2384
+ $_len = strlen($_text);
2385
+ $_i = 0;
2386
+ if ($_pos) {
2387
+ $_orig_pos = $_pos;
2388
+ $_max = '.$block_size.' - $_pos;
2389
+ if ($_len >= $_max) {
2390
+ $_i = $_max;
2391
+ $_len-= $_max;
2392
+ $_pos = 0;
2393
+ } else {
2394
+ $_i = $_len;
2395
+ $_pos+= $_len;
2396
+ $_len = 0;
2397
+ }
2398
+ $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
2399
+ $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
2400
+ }
2401
+ while ($_len >= '.$block_size.') {
2402
+ $in = $_iv;
2403
+ '.$encrypt_block.'
2404
+ $_iv = $in;
2405
+ $cb = substr($_text, $_i, '.$block_size.');
2406
+ $_plaintext.= $_iv ^ $cb;
2407
+ $_iv = $cb;
2408
+ $_len-= '.$block_size.';
2409
+ $_i+= '.$block_size.';
2410
+ }
2411
+ if ($_len) {
2412
+ $in = $_iv;
2413
+ '.$encrypt_block.'
2414
+ $_iv = $in;
2415
+ $_plaintext.= $_iv ^ substr($_text, $_i);
2416
+ $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
2417
+ $_pos = $_len;
2418
+ }
2419
+
2420
+ return $_plaintext;
2421
+ ';
2422
+ break;
2423
+ case CRYPT_MODE_OFB:
2424
+ $encrypt = $init_encrypt . '
2425
+ $_ciphertext = "";
2426
+ $_plaintext_len = strlen($_text);
2427
+ $_xor = $self->encryptIV;
2428
+ $_buffer = &$self->enbuffer;
2429
+
2430
+ if (strlen($_buffer["xor"])) {
2431
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2432
+ $_block = substr($_text, $_i, '.$block_size.');
2433
+ if (strlen($_block) > strlen($_buffer["xor"])) {
2434
+ $in = $_xor;
2435
+ '.$encrypt_block.'
2436
+ $_xor = $in;
2437
+ $_buffer["xor"].= $_xor;
2438
+ }
2439
+ $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2440
+ $_ciphertext.= $_block ^ $_key;
2441
+ }
2442
+ } else {
2443
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2444
+ $in = $_xor;
2445
+ '.$encrypt_block.'
2446
+ $_xor = $in;
2447
+ $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2448
+ }
2449
+ $_key = $_xor;
2450
+ }
2451
+ if ($self->continuousBuffer) {
2452
+ $self->encryptIV = $_xor;
2453
+ if ($_start = $_plaintext_len % '.$block_size.') {
2454
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2455
+ }
2456
+ }
2457
+ return $_ciphertext;
2458
+ ';
2459
+
2460
+ $decrypt = $init_encrypt . '
2461
+ $_plaintext = "";
2462
+ $_ciphertext_len = strlen($_text);
2463
+ $_xor = $self->decryptIV;
2464
+ $_buffer = &$self->debuffer;
2465
+
2466
+ if (strlen($_buffer["xor"])) {
2467
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2468
+ $_block = substr($_text, $_i, '.$block_size.');
2469
+ if (strlen($_block) > strlen($_buffer["xor"])) {
2470
+ $in = $_xor;
2471
+ '.$encrypt_block.'
2472
+ $_xor = $in;
2473
+ $_buffer["xor"].= $_xor;
2474
+ }
2475
+ $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2476
+ $_plaintext.= $_block ^ $_key;
2477
+ }
2478
+ } else {
2479
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2480
+ $in = $_xor;
2481
+ '.$encrypt_block.'
2482
+ $_xor = $in;
2483
+ $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2484
+ }
2485
+ $_key = $_xor;
2486
+ }
2487
+ if ($self->continuousBuffer) {
2488
+ $self->decryptIV = $_xor;
2489
+ if ($_start = $_ciphertext_len % '.$block_size.') {
2490
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2491
+ }
2492
+ }
2493
+ return $_plaintext;
2494
+ ';
2495
+ break;
2496
+ case CRYPT_MODE_STREAM:
2497
+ $encrypt = $init_encrypt . '
2498
+ $_ciphertext = "";
2499
+ '.$encrypt_block.'
2500
+ return $_ciphertext;
2501
+ ';
2502
+ $decrypt = $init_decrypt . '
2503
+ $_plaintext = "";
2504
+ '.$decrypt_block.'
2505
+ return $_plaintext;
2506
+ ';
2507
+ break;
2508
+ // case CRYPT_MODE_CBC:
2509
+ default:
2510
+ $encrypt = $init_encrypt . '
2511
+ $_ciphertext = "";
2512
+ $_plaintext_len = strlen($_text);
2513
+
2514
+ $in = $self->encryptIV;
2515
+
2516
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2517
+ $in = substr($_text, $_i, '.$block_size.') ^ $in;
2518
+ '.$encrypt_block.'
2519
+ $_ciphertext.= $in;
2520
+ }
2521
+
2522
+ if ($self->continuousBuffer) {
2523
+ $self->encryptIV = $in;
2524
+ }
2525
+
2526
+ return $_ciphertext;
2527
+ ';
2528
+
2529
+ $decrypt = $init_decrypt . '
2530
+ $_plaintext = "";
2531
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2532
+ $_ciphertext_len = strlen($_text);
2533
+
2534
+ $_iv = $self->decryptIV;
2535
+
2536
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2537
+ $in = $_block = substr($_text, $_i, '.$block_size.');
2538
+ '.$decrypt_block.'
2539
+ $_plaintext.= $in ^ $_iv;
2540
+ $_iv = $_block;
2541
+ }
2542
+
2543
+ if ($self->continuousBuffer) {
2544
+ $self->decryptIV = $_iv;
2545
+ }
2546
+
2547
+ return $self->_unpad($_plaintext);
2548
+ ';
2549
+ break;
2550
+ }
2551
+
2552
+ // Create the $inline function and return its name as string. Ready to run!
2553
+ return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
2554
+ }
2555
+
2556
+ /**
2557
+ * Holds the lambda_functions table (classwide)
2558
+ *
2559
+ * Each name of the lambda function, created from
2560
+ * _setupInlineCrypt() && _createInlineCryptFunction()
2561
+ * is stored, classwide (!), here for reusing.
2562
+ *
2563
+ * The string-based index of $function is a classwide
2564
+ * unique value representing, at least, the $mode of
2565
+ * operation (or more... depends of the optimizing level)
2566
+ * for which $mode the lambda function was created.
2567
+ *
2568
+ * @access private
2569
+ * @return array &$functions
2570
+ */
2571
+ function &_getLambdaFunctions()
2572
+ {
2573
+ static $functions = array();
2574
+ return $functions;
2575
+ }
2576
+
2577
+ /**
2578
+ * Generates a digest from $bytes
2579
+ *
2580
+ * @see self::_setupInlineCrypt()
2581
+ * @access private
2582
+ * @param $bytes
2583
+ * @return string
2584
+ */
2585
+ function _hashInlineCryptFunction($bytes)
2586
+ {
2587
+ if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) {
2588
+ define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool', hash_algos())));
2589
+ }
2590
+
2591
+ $result = '';
2592
+ $hash = $bytes;
2593
+
2594
+ switch (true) {
2595
+ case CRYPT_BASE_WHIRLPOOL_AVAILABLE:
2596
+ foreach (str_split($bytes, 64) as $t) {
2597
+ $hash = hash('whirlpool', $hash, true);
2598
+ $result .= $t ^ $hash;
2599
+ }
2600
+ return $result . hash('whirlpool', $hash, true);
2601
+ default:
2602
+ $len = strlen($bytes);
2603
+ for ($i = 0; $i < $len; $i+=20) {
2604
+ $t = substr($bytes, $i, 20);
2605
+ $hash = pack('H*', sha1($hash));
2606
+ $result .= $t ^ $hash;
2607
+ }
2608
+ return $result . pack('H*', sha1($hash));
2609
+ }
2610
+ }
2611
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php ADDED
@@ -0,0 +1,671 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of Blowfish.
5
+ *
6
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * Useful resources are as follows:
11
+ *
12
+ * - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
13
+ *
14
+ * Here's a short example of how to use this library:
15
+ * <code>
16
+ * <?php
17
+ * include 'Crypt/Blowfish.php';
18
+ *
19
+ * $blowfish = new Crypt_Blowfish();
20
+ *
21
+ * $blowfish->setKey('12345678901234567890123456789012');
22
+ *
23
+ * $plaintext = str_repeat('a', 1024);
24
+ *
25
+ * echo $blowfish->decrypt($blowfish->encrypt($plaintext));
26
+ * ?>
27
+ * </code>
28
+ *
29
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * of this software and associated documentation files (the "Software"), to deal
31
+ * in the Software without restriction, including without limitation the rights
32
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ * copies of the Software, and to permit persons to whom the Software is
34
+ * furnished to do so, subject to the following conditions:
35
+ *
36
+ * The above copyright notice and this permission notice shall be included in
37
+ * all copies or substantial portions of the Software.
38
+ *
39
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * THE SOFTWARE.
46
+ *
47
+ * @category Crypt
48
+ * @package Crypt_Blowfish
49
+ * @author Jim Wigginton <terrafrost@php.net>
50
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
51
+ * @copyright 2007 Jim Wigginton
52
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
53
+ * @link http://phpseclib.sourceforge.net
54
+ */
55
+
56
+ /**
57
+ * Include Crypt_Base
58
+ *
59
+ * Base cipher class
60
+ */
61
+ if (!class_exists('Crypt_Base')) {
62
+ include_once 'Base.php';
63
+ }
64
+
65
+ /**#@+
66
+ * @access public
67
+ * @see self::encrypt()
68
+ * @see self::decrypt()
69
+ */
70
+ /**
71
+ * Encrypt / decrypt using the Counter mode.
72
+ *
73
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
74
+ *
75
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
76
+ */
77
+ define('CRYPT_BLOWFISH_MODE_CTR', CRYPT_MODE_CTR);
78
+ /**
79
+ * Encrypt / decrypt using the Electronic Code Book mode.
80
+ *
81
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
82
+ */
83
+ define('CRYPT_BLOWFISH_MODE_ECB', CRYPT_MODE_ECB);
84
+ /**
85
+ * Encrypt / decrypt using the Code Book Chaining mode.
86
+ *
87
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
88
+ */
89
+ define('CRYPT_BLOWFISH_MODE_CBC', CRYPT_MODE_CBC);
90
+ /**
91
+ * Encrypt / decrypt using the Cipher Feedback mode.
92
+ *
93
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
94
+ */
95
+ define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
96
+ /**
97
+ * Encrypt / decrypt using the Cipher Feedback mode.
98
+ *
99
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
100
+ */
101
+ define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
102
+ /**#@-*/
103
+
104
+ /**
105
+ * Pure-PHP implementation of Blowfish.
106
+ *
107
+ * @package Crypt_Blowfish
108
+ * @author Jim Wigginton <terrafrost@php.net>
109
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
110
+ * @access public
111
+ */
112
+ class Crypt_Blowfish extends Crypt_Base
113
+ {
114
+ /**
115
+ * Block Length of the cipher
116
+ *
117
+ * @see Crypt_Base::block_size
118
+ * @var int
119
+ * @access private
120
+ */
121
+ var $block_size = 8;
122
+
123
+ /**
124
+ * The namespace used by the cipher for its constants.
125
+ *
126
+ * @see Crypt_Base::const_namespace
127
+ * @var string
128
+ * @access private
129
+ */
130
+ var $const_namespace = 'BLOWFISH';
131
+
132
+ /**
133
+ * The mcrypt specific name of the cipher
134
+ *
135
+ * @see Crypt_Base::cipher_name_mcrypt
136
+ * @var string
137
+ * @access private
138
+ */
139
+ var $cipher_name_mcrypt = 'blowfish';
140
+
141
+ /**
142
+ * Optimizing value while CFB-encrypting
143
+ *
144
+ * @see Crypt_Base::cfb_init_len
145
+ * @var int
146
+ * @access private
147
+ */
148
+ var $cfb_init_len = 500;
149
+
150
+ /**
151
+ * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
152
+ *
153
+ * S-Box 0
154
+ *
155
+ * @access private
156
+ * @var array
157
+ */
158
+ var $sbox0 = array(
159
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
160
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
161
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
162
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
163
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
164
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
165
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
166
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
167
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
168
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
169
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
170
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
171
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
172
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
173
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
174
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
175
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
176
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
177
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
178
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
179
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
180
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
181
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
182
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
183
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
184
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
185
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
186
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
187
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
188
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
189
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
190
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
191
+ );
192
+
193
+ /**
194
+ * S-Box 1
195
+ *
196
+ * @access private
197
+ * @var array
198
+ */
199
+ var $sbox1 = array(
200
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
201
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
202
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
203
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
204
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
205
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
206
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
207
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
208
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
209
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
210
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
211
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
212
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
213
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
214
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
215
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
216
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
217
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
218
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
219
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
220
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
221
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
222
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
223
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
224
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
225
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
226
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
227
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
228
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
229
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
230
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
231
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
232
+ );
233
+
234
+ /**
235
+ * S-Box 2
236
+ *
237
+ * @access private
238
+ * @var array
239
+ */
240
+ var $sbox2 = array(
241
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
242
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
243
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
244
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
245
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
246
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
247
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
248
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
249
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
250
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
251
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
252
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
253
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
254
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
255
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
256
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
257
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
258
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
259
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
260
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
261
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
262
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
263
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
264
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
265
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
266
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
267
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
268
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
269
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
270
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
271
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
272
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
273
+ );
274
+
275
+ /**
276
+ * S-Box 3
277
+ *
278
+ * @access private
279
+ * @var array
280
+ */
281
+ var $sbox3 = array(
282
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
283
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
284
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
285
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
286
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
287
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
288
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
289
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
290
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
291
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
292
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
293
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
294
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
295
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
296
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
297
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
298
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
299
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
300
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
301
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
302
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
303
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
304
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
305
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
306
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
307
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
308
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
309
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
310
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
311
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
312
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
313
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
314
+ );
315
+
316
+ /**
317
+ * P-Array consists of 18 32-bit subkeys
318
+ *
319
+ * @var array
320
+ * @access private
321
+ */
322
+ var $parray = array(
323
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
324
+ 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
325
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
326
+ );
327
+
328
+ /**
329
+ * The BCTX-working Array
330
+ *
331
+ * Holds the expanded key [p] and the key-depended s-boxes [sb]
332
+ *
333
+ * @var array
334
+ * @access private
335
+ */
336
+ var $bctx;
337
+
338
+ /**
339
+ * Holds the last used key
340
+ *
341
+ * @var array
342
+ * @access private
343
+ */
344
+ var $kl;
345
+
346
+ /**
347
+ * The Key Length (in bytes)
348
+ *
349
+ * @see Crypt_Base::setKeyLength()
350
+ * @var int
351
+ * @access private
352
+ * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
353
+ * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
354
+ * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
355
+ * of that, we'll just precompute it once.
356
+ */
357
+ var $key_length = 16;
358
+
359
+ /**
360
+ * Sets the key length.
361
+ *
362
+ * Key lengths can be between 32 and 448 bits.
363
+ *
364
+ * @access public
365
+ * @param int $length
366
+ */
367
+ function setKeyLength($length)
368
+ {
369
+ if ($length < 32) {
370
+ $this->key_length = 7;
371
+ } elseif ($length > 448) {
372
+ $this->key_length = 56;
373
+ } else {
374
+ $this->key_length = $length >> 3;
375
+ }
376
+
377
+ parent::setKeyLength($length);
378
+ }
379
+
380
+ /**
381
+ * Test for engine validity
382
+ *
383
+ * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
384
+ *
385
+ * @see Crypt_Base::isValidEngine()
386
+ * @param int $engine
387
+ * @access public
388
+ * @return bool
389
+ */
390
+ function isValidEngine($engine)
391
+ {
392
+ if ($engine == CRYPT_ENGINE_OPENSSL) {
393
+ if ($this->key_length < 16) {
394
+ return false;
395
+ }
396
+ $this->cipher_name_openssl_ecb = 'bf-ecb';
397
+ $this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
398
+ }
399
+
400
+ return parent::isValidEngine($engine);
401
+ }
402
+
403
+ /**
404
+ * Setup the key (expansion)
405
+ *
406
+ * @see Crypt_Base::_setupKey()
407
+ * @access private
408
+ */
409
+ function _setupKey()
410
+ {
411
+ if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
412
+ // already expanded
413
+ return;
414
+ }
415
+ $this->kl = array('key' => $this->key);
416
+
417
+ /* key-expanding p[] and S-Box building sb[] */
418
+ $this->bctx = array(
419
+ 'p' => array(),
420
+ 'sb' => array(
421
+ $this->sbox0,
422
+ $this->sbox1,
423
+ $this->sbox2,
424
+ $this->sbox3
425
+ )
426
+ );
427
+
428
+ // unpack binary string in unsigned chars
429
+ $key = array_values(unpack('C*', $this->key));
430
+ $keyl = count($key);
431
+ for ($j = 0, $i = 0; $i < 18; ++$i) {
432
+ // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
433
+ for ($data = 0, $k = 0; $k < 4; ++$k) {
434
+ $data = ($data << 8) | $key[$j];
435
+ if (++$j >= $keyl) {
436
+ $j = 0;
437
+ }
438
+ }
439
+ $this->bctx['p'][] = $this->parray[$i] ^ $data;
440
+ }
441
+
442
+ // encrypt the zero-string, replace P1 and P2 with the encrypted data,
443
+ // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
444
+ $data = "\0\0\0\0\0\0\0\0";
445
+ for ($i = 0; $i < 18; $i += 2) {
446
+ list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
447
+ $this->bctx['p'][$i ] = $l;
448
+ $this->bctx['p'][$i + 1] = $r;
449
+ }
450
+ for ($i = 0; $i < 4; ++$i) {
451
+ for ($j = 0; $j < 256; $j += 2) {
452
+ list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
453
+ $this->bctx['sb'][$i][$j ] = $l;
454
+ $this->bctx['sb'][$i][$j + 1] = $r;
455
+ }
456
+ }
457
+ }
458
+
459
+ /**
460
+ * Encrypts a block
461
+ *
462
+ * @access private
463
+ * @param string $in
464
+ * @return string
465
+ */
466
+ function _encryptBlock($in)
467
+ {
468
+ $p = $this->bctx["p"];
469
+ // extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower
470
+ $sb_0 = $this->bctx["sb"][0];
471
+ $sb_1 = $this->bctx["sb"][1];
472
+ $sb_2 = $this->bctx["sb"][2];
473
+ $sb_3 = $this->bctx["sb"][3];
474
+
475
+ $in = unpack("N*", $in);
476
+ $l = $in[1];
477
+ $r = $in[2];
478
+
479
+ for ($i = 0; $i < 16; $i+= 2) {
480
+ $l^= $p[$i];
481
+ $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
482
+ $sb_2[$l >> 8 & 0xff]) +
483
+ $sb_3[$l & 0xff]);
484
+
485
+ $r^= $p[$i + 1];
486
+ $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
487
+ $sb_2[$r >> 8 & 0xff]) +
488
+ $sb_3[$r & 0xff]);
489
+ }
490
+ return pack("N*", $r ^ $p[17], $l ^ $p[16]);
491
+ }
492
+
493
+ /**
494
+ * Decrypts a block
495
+ *
496
+ * @access private
497
+ * @param string $in
498
+ * @return string
499
+ */
500
+ function _decryptBlock($in)
501
+ {
502
+ $p = $this->bctx["p"];
503
+ $sb_0 = $this->bctx["sb"][0];
504
+ $sb_1 = $this->bctx["sb"][1];
505
+ $sb_2 = $this->bctx["sb"][2];
506
+ $sb_3 = $this->bctx["sb"][3];
507
+
508
+ $in = unpack("N*", $in);
509
+ $l = $in[1];
510
+ $r = $in[2];
511
+
512
+ for ($i = 17; $i > 2; $i-= 2) {
513
+ $l^= $p[$i];
514
+ $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
515
+ $sb_2[$l >> 8 & 0xff]) +
516
+ $sb_3[$l & 0xff]);
517
+
518
+ $r^= $p[$i - 1];
519
+ $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
520
+ $sb_2[$r >> 8 & 0xff]) +
521
+ $sb_3[$r & 0xff]);
522
+ }
523
+ return pack("N*", $r ^ $p[0], $l ^ $p[1]);
524
+ }
525
+
526
+ /**
527
+ * Setup the performance-optimized function for de/encrypt()
528
+ *
529
+ * @see Crypt_Base::_setupInlineCrypt()
530
+ * @access private
531
+ */
532
+ function _setupInlineCrypt()
533
+ {
534
+ $lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
535
+
536
+ // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
537
+ // (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
538
+ // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
539
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
540
+
541
+ // Generation of a unique hash for our generated code
542
+ $code_hash = "Crypt_Blowfish, {$this->mode}";
543
+ if ($gen_hi_opt_code) {
544
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
545
+ }
546
+
547
+ // on 32-bit linux systems with PHP < 5.3 float to integer conversion is bad
548
+ switch (true) {
549
+ case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
550
+ case version_compare(PHP_VERSION, '5.3.0') >= 0:
551
+ case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
552
+ $safeint = '%s';
553
+ break;
554
+ default:
555
+ $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
556
+ $safeint.= '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
557
+ }
558
+
559
+ if (!isset($lambda_functions[$code_hash])) {
560
+ switch (true) {
561
+ case $gen_hi_opt_code:
562
+ $p = $this->bctx['p'];
563
+ $init_crypt = '
564
+ static $sb_0, $sb_1, $sb_2, $sb_3;
565
+ if (!$sb_0) {
566
+ $sb_0 = $self->bctx["sb"][0];
567
+ $sb_1 = $self->bctx["sb"][1];
568
+ $sb_2 = $self->bctx["sb"][2];
569
+ $sb_3 = $self->bctx["sb"][3];
570
+ }
571
+ ';
572
+ break;
573
+ default:
574
+ $p = array();
575
+ for ($i = 0; $i < 18; ++$i) {
576
+ $p[] = '$p_' . $i;
577
+ }
578
+ $init_crypt = '
579
+ list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
580
+ list(' . implode(',', $p) . ') = $self->bctx["p"];
581
+
582
+ ';
583
+ }
584
+
585
+ // Generating encrypt code:
586
+ $encrypt_block = '
587
+ $in = unpack("N*", $in);
588
+ $l = $in[1];
589
+ $r = $in[2];
590
+ ';
591
+ for ($i = 0; $i < 16; $i+= 2) {
592
+ $encrypt_block.= '
593
+ $l^= ' . $p[$i] . ';
594
+ $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
595
+ $sb_2[$l >> 8 & 0xff]) +
596
+ $sb_3[$l & 0xff]') . ';
597
+
598
+ $r^= ' . $p[$i + 1] . ';
599
+ $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
600
+ $sb_2[$r >> 8 & 0xff]) +
601
+ $sb_3[$r & 0xff]') . ';
602
+ ';
603
+ }
604
+ $encrypt_block.= '
605
+ $in = pack("N*",
606
+ $r ^ ' . $p[17] . ',
607
+ $l ^ ' . $p[16] . '
608
+ );
609
+ ';
610
+
611
+ // Generating decrypt code:
612
+ $decrypt_block = '
613
+ $in = unpack("N*", $in);
614
+ $l = $in[1];
615
+ $r = $in[2];
616
+ ';
617
+
618
+ for ($i = 17; $i > 2; $i-= 2) {
619
+ $decrypt_block.= '
620
+ $l^= ' . $p[$i] . ';
621
+ $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
622
+ $sb_2[$l >> 8 & 0xff]) +
623
+ $sb_3[$l & 0xff]') . ';
624
+
625
+ $r^= ' . $p[$i - 1] . ';
626
+ $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
627
+ $sb_2[$r >> 8 & 0xff]) +
628
+ $sb_3[$r & 0xff]') . ';
629
+ ';
630
+ }
631
+
632
+ $decrypt_block.= '
633
+ $in = pack("N*",
634
+ $r ^ ' . $p[0] . ',
635
+ $l ^ ' . $p[1] . '
636
+ );
637
+ ';
638
+
639
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
640
+ array(
641
+ 'init_crypt' => $init_crypt,
642
+ 'init_encrypt' => '',
643
+ 'init_decrypt' => '',
644
+ 'encrypt_block' => $encrypt_block,
645
+ 'decrypt_block' => $decrypt_block
646
+ )
647
+ );
648
+ }
649
+ $this->inline_crypt = $lambda_functions[$code_hash];
650
+ }
651
+
652
+ /**
653
+ * Convert float to int
654
+ *
655
+ * On 32-bit Linux installs running PHP < 5.3 converting floats to ints doesn't always work
656
+ *
657
+ * @access private
658
+ * @param string $x
659
+ * @return int
660
+ */
661
+ function safe_intval($x)
662
+ {
663
+ // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
664
+ // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
665
+ if (is_int($x) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
666
+ return $x;
667
+ }
668
+ return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
669
+ ((fmod(floor($x / 0x80000000), 2) & 1) << 31);
670
+ }
671
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php ADDED
@@ -0,0 +1,1516 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of DES.
5
+ *
6
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * Useful resources are as follows:
11
+ *
12
+ * - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
13
+ * - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
14
+ * - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
15
+ *
16
+ * Here's a short example of how to use this library:
17
+ * <code>
18
+ * <?php
19
+ * include 'Crypt/DES.php';
20
+ *
21
+ * $des = new Crypt_DES();
22
+ *
23
+ * $des->setKey('abcdefgh');
24
+ *
25
+ * $size = 10 * 1024;
26
+ * $plaintext = '';
27
+ * for ($i = 0; $i < $size; $i++) {
28
+ * $plaintext.= 'a';
29
+ * }
30
+ *
31
+ * echo $des->decrypt($des->encrypt($plaintext));
32
+ * ?>
33
+ * </code>
34
+ *
35
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
36
+ * of this software and associated documentation files (the "Software"), to deal
37
+ * in the Software without restriction, including without limitation the rights
38
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39
+ * copies of the Software, and to permit persons to whom the Software is
40
+ * furnished to do so, subject to the following conditions:
41
+ *
42
+ * The above copyright notice and this permission notice shall be included in
43
+ * all copies or substantial portions of the Software.
44
+ *
45
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
51
+ * THE SOFTWARE.
52
+ *
53
+ * @category Crypt
54
+ * @package Crypt_DES
55
+ * @author Jim Wigginton <terrafrost@php.net>
56
+ * @copyright 2007 Jim Wigginton
57
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
58
+ * @link http://phpseclib.sourceforge.net
59
+ */
60
+
61
+ /**
62
+ * Include Crypt_Base
63
+ *
64
+ * Base cipher class
65
+ */
66
+ if (!class_exists('Crypt_Base')) {
67
+ include_once 'Base.php';
68
+ }
69
+
70
+ /**#@+
71
+ * @access private
72
+ * @see self::_setupKey()
73
+ * @see self::_processBlock()
74
+ */
75
+ /**
76
+ * Contains $keys[CRYPT_DES_ENCRYPT]
77
+ */
78
+ define('CRYPT_DES_ENCRYPT', 0);
79
+ /**
80
+ * Contains $keys[CRYPT_DES_DECRYPT]
81
+ */
82
+ define('CRYPT_DES_DECRYPT', 1);
83
+ /**#@-*/
84
+
85
+ /**#@+
86
+ * @access public
87
+ * @see self::encrypt()
88
+ * @see self::decrypt()
89
+ */
90
+ /**
91
+ * Encrypt / decrypt using the Counter mode.
92
+ *
93
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
94
+ *
95
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
96
+ */
97
+ define('CRYPT_DES_MODE_CTR', CRYPT_MODE_CTR);
98
+ /**
99
+ * Encrypt / decrypt using the Electronic Code Book mode.
100
+ *
101
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
102
+ */
103
+ define('CRYPT_DES_MODE_ECB', CRYPT_MODE_ECB);
104
+ /**
105
+ * Encrypt / decrypt using the Code Book Chaining mode.
106
+ *
107
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
108
+ */
109
+ define('CRYPT_DES_MODE_CBC', CRYPT_MODE_CBC);
110
+ /**
111
+ * Encrypt / decrypt using the Cipher Feedback mode.
112
+ *
113
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
114
+ */
115
+ define('CRYPT_DES_MODE_CFB', CRYPT_MODE_CFB);
116
+ /**
117
+ * Encrypt / decrypt using the Cipher Feedback mode.
118
+ *
119
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
120
+ */
121
+ define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB);
122
+ /**#@-*/
123
+
124
+ /**
125
+ * Pure-PHP implementation of DES.
126
+ *
127
+ * @package Crypt_DES
128
+ * @author Jim Wigginton <terrafrost@php.net>
129
+ * @access public
130
+ */
131
+ class Crypt_DES extends Crypt_Base
132
+ {
133
+ /**
134
+ * Block Length of the cipher
135
+ *
136
+ * @see Crypt_Base::block_size
137
+ * @var int
138
+ * @access private
139
+ */
140
+ var $block_size = 8;
141
+
142
+ /**
143
+ * Key Length (in bytes)
144
+ *
145
+ * @see Crypt_Base::setKeyLength()
146
+ * @var int
147
+ * @access private
148
+ */
149
+ var $key_length = 8;
150
+
151
+ /**
152
+ * The namespace used by the cipher for its constants.
153
+ *
154
+ * @see Crypt_Base::const_namespace
155
+ * @var string
156
+ * @access private
157
+ */
158
+ var $const_namespace = 'DES';
159
+
160
+ /**
161
+ * The mcrypt specific name of the cipher
162
+ *
163
+ * @see Crypt_Base::cipher_name_mcrypt
164
+ * @var string
165
+ * @access private
166
+ */
167
+ var $cipher_name_mcrypt = 'des';
168
+
169
+ /**
170
+ * The OpenSSL names of the cipher / modes
171
+ *
172
+ * @see Crypt_Base::openssl_mode_names
173
+ * @var array
174
+ * @access private
175
+ */
176
+ var $openssl_mode_names = array(
177
+ CRYPT_MODE_ECB => 'des-ecb',
178
+ CRYPT_MODE_CBC => 'des-cbc',
179
+ CRYPT_MODE_CFB => 'des-cfb',
180
+ CRYPT_MODE_OFB => 'des-ofb'
181
+ // CRYPT_MODE_CTR is undefined for DES
182
+ );
183
+
184
+ /**
185
+ * Optimizing value while CFB-encrypting
186
+ *
187
+ * @see Crypt_Base::cfb_init_len
188
+ * @var int
189
+ * @access private
190
+ */
191
+ var $cfb_init_len = 500;
192
+
193
+ /**
194
+ * Switch for DES/3DES encryption
195
+ *
196
+ * Used only if $engine == CRYPT_DES_MODE_INTERNAL
197
+ *
198
+ * @see self::_setupKey()
199
+ * @see self::_processBlock()
200
+ * @var int
201
+ * @access private
202
+ */
203
+ var $des_rounds = 1;
204
+
205
+ /**
206
+ * max possible size of $key
207
+ *
208
+ * @see self::setKey()
209
+ * @var string
210
+ * @access private
211
+ */
212
+ var $key_length_max = 8;
213
+
214
+ /**
215
+ * The Key Schedule
216
+ *
217
+ * @see self::_setupKey()
218
+ * @var array
219
+ * @access private
220
+ */
221
+ var $keys;
222
+
223
+ /**
224
+ * Shuffle table.
225
+ *
226
+ * For each byte value index, the entry holds an 8-byte string
227
+ * with each byte containing all bits in the same state as the
228
+ * corresponding bit in the index value.
229
+ *
230
+ * @see self::_processBlock()
231
+ * @see self::_setupKey()
232
+ * @var array
233
+ * @access private
234
+ */
235
+ var $shuffle = array(
236
+ "\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xFF",
237
+ "\x00\x00\x00\x00\x00\x00\xFF\x00", "\x00\x00\x00\x00\x00\x00\xFF\xFF",
238
+ "\x00\x00\x00\x00\x00\xFF\x00\x00", "\x00\x00\x00\x00\x00\xFF\x00\xFF",
239
+ "\x00\x00\x00\x00\x00\xFF\xFF\x00", "\x00\x00\x00\x00\x00\xFF\xFF\xFF",
240
+ "\x00\x00\x00\x00\xFF\x00\x00\x00", "\x00\x00\x00\x00\xFF\x00\x00\xFF",
241
+ "\x00\x00\x00\x00\xFF\x00\xFF\x00", "\x00\x00\x00\x00\xFF\x00\xFF\xFF",
242
+ "\x00\x00\x00\x00\xFF\xFF\x00\x00", "\x00\x00\x00\x00\xFF\xFF\x00\xFF",
243
+ "\x00\x00\x00\x00\xFF\xFF\xFF\x00", "\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
244
+ "\x00\x00\x00\xFF\x00\x00\x00\x00", "\x00\x00\x00\xFF\x00\x00\x00\xFF",
245
+ "\x00\x00\x00\xFF\x00\x00\xFF\x00", "\x00\x00\x00\xFF\x00\x00\xFF\xFF",
246
+ "\x00\x00\x00\xFF\x00\xFF\x00\x00", "\x00\x00\x00\xFF\x00\xFF\x00\xFF",
247
+ "\x00\x00\x00\xFF\x00\xFF\xFF\x00", "\x00\x00\x00\xFF\x00\xFF\xFF\xFF",
248
+ "\x00\x00\x00\xFF\xFF\x00\x00\x00", "\x00\x00\x00\xFF\xFF\x00\x00\xFF",
249
+ "\x00\x00\x00\xFF\xFF\x00\xFF\x00", "\x00\x00\x00\xFF\xFF\x00\xFF\xFF",
250
+ "\x00\x00\x00\xFF\xFF\xFF\x00\x00", "\x00\x00\x00\xFF\xFF\xFF\x00\xFF",
251
+ "\x00\x00\x00\xFF\xFF\xFF\xFF\x00", "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF",
252
+ "\x00\x00\xFF\x00\x00\x00\x00\x00", "\x00\x00\xFF\x00\x00\x00\x00\xFF",
253
+ "\x00\x00\xFF\x00\x00\x00\xFF\x00", "\x00\x00\xFF\x00\x00\x00\xFF\xFF",
254
+ "\x00\x00\xFF\x00\x00\xFF\x00\x00", "\x00\x00\xFF\x00\x00\xFF\x00\xFF",
255
+ "\x00\x00\xFF\x00\x00\xFF\xFF\x00", "\x00\x00\xFF\x00\x00\xFF\xFF\xFF",
256
+ "\x00\x00\xFF\x00\xFF\x00\x00\x00", "\x00\x00\xFF\x00\xFF\x00\x00\xFF",
257
+ "\x00\x00\xFF\x00\xFF\x00\xFF\x00", "\x00\x00\xFF\x00\xFF\x00\xFF\xFF",
258
+ "\x00\x00\xFF\x00\xFF\xFF\x00\x00", "\x00\x00\xFF\x00\xFF\xFF\x00\xFF",
259
+ "\x00\x00\xFF\x00\xFF\xFF\xFF\x00", "\x00\x00\xFF\x00\xFF\xFF\xFF\xFF",
260
+ "\x00\x00\xFF\xFF\x00\x00\x00\x00", "\x00\x00\xFF\xFF\x00\x00\x00\xFF",
261
+ "\x00\x00\xFF\xFF\x00\x00\xFF\x00", "\x00\x00\xFF\xFF\x00\x00\xFF\xFF",
262
+ "\x00\x00\xFF\xFF\x00\xFF\x00\x00", "\x00\x00\xFF\xFF\x00\xFF\x00\xFF",
263
+ "\x00\x00\xFF\xFF\x00\xFF\xFF\x00", "\x00\x00\xFF\xFF\x00\xFF\xFF\xFF",
264
+ "\x00\x00\xFF\xFF\xFF\x00\x00\x00", "\x00\x00\xFF\xFF\xFF\x00\x00\xFF",
265
+ "\x00\x00\xFF\xFF\xFF\x00\xFF\x00", "\x00\x00\xFF\xFF\xFF\x00\xFF\xFF",
266
+ "\x00\x00\xFF\xFF\xFF\xFF\x00\x00", "\x00\x00\xFF\xFF\xFF\xFF\x00\xFF",
267
+ "\x00\x00\xFF\xFF\xFF\xFF\xFF\x00", "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
268
+ "\x00\xFF\x00\x00\x00\x00\x00\x00", "\x00\xFF\x00\x00\x00\x00\x00\xFF",
269
+ "\x00\xFF\x00\x00\x00\x00\xFF\x00", "\x00\xFF\x00\x00\x00\x00\xFF\xFF",
270
+ "\x00\xFF\x00\x00\x00\xFF\x00\x00", "\x00\xFF\x00\x00\x00\xFF\x00\xFF",
271
+ "\x00\xFF\x00\x00\x00\xFF\xFF\x00", "\x00\xFF\x00\x00\x00\xFF\xFF\xFF",
272
+ "\x00\xFF\x00\x00\xFF\x00\x00\x00", "\x00\xFF\x00\x00\xFF\x00\x00\xFF",
273
+ "\x00\xFF\x00\x00\xFF\x00\xFF\x00", "\x00\xFF\x00\x00\xFF\x00\xFF\xFF",
274
+ "\x00\xFF\x00\x00\xFF\xFF\x00\x00", "\x00\xFF\x00\x00\xFF\xFF\x00\xFF",
275
+ "\x00\xFF\x00\x00\xFF\xFF\xFF\x00", "\x00\xFF\x00\x00\xFF\xFF\xFF\xFF",
276
+ "\x00\xFF\x00\xFF\x00\x00\x00\x00", "\x00\xFF\x00\xFF\x00\x00\x00\xFF",
277
+ "\x00\xFF\x00\xFF\x00\x00\xFF\x00", "\x00\xFF\x00\xFF\x00\x00\xFF\xFF",
278
+ "\x00\xFF\x00\xFF\x00\xFF\x00\x00", "\x00\xFF\x00\xFF\x00\xFF\x00\xFF",
279
+ "\x00\xFF\x00\xFF\x00\xFF\xFF\x00", "\x00\xFF\x00\xFF\x00\xFF\xFF\xFF",
280
+ "\x00\xFF\x00\xFF\xFF\x00\x00\x00", "\x00\xFF\x00\xFF\xFF\x00\x00\xFF",
281
+ "\x00\xFF\x00\xFF\xFF\x00\xFF\x00", "\x00\xFF\x00\xFF\xFF\x00\xFF\xFF",
282
+ "\x00\xFF\x00\xFF\xFF\xFF\x00\x00", "\x00\xFF\x00\xFF\xFF\xFF\x00\xFF",
283
+ "\x00\xFF\x00\xFF\xFF\xFF\xFF\x00", "\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF",
284
+ "\x00\xFF\xFF\x00\x00\x00\x00\x00", "\x00\xFF\xFF\x00\x00\x00\x00\xFF",
285
+ "\x00\xFF\xFF\x00\x00\x00\xFF\x00", "\x00\xFF\xFF\x00\x00\x00\xFF\xFF",
286
+ "\x00\xFF\xFF\x00\x00\xFF\x00\x00", "\x00\xFF\xFF\x00\x00\xFF\x00\xFF",
287
+ "\x00\xFF\xFF\x00\x00\xFF\xFF\x00", "\x00\xFF\xFF\x00\x00\xFF\xFF\xFF",
288
+ "\x00\xFF\xFF\x00\xFF\x00\x00\x00", "\x00\xFF\xFF\x00\xFF\x00\x00\xFF",
289
+ "\x00\xFF\xFF\x00\xFF\x00\xFF\x00", "\x00\xFF\xFF\x00\xFF\x00\xFF\xFF",
290
+ "\x00\xFF\xFF\x00\xFF\xFF\x00\x00", "\x00\xFF\xFF\x00\xFF\xFF\x00\xFF",
291
+ "\x00\xFF\xFF\x00\xFF\xFF\xFF\x00", "\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF",
292
+ "\x00\xFF\xFF\xFF\x00\x00\x00\x00", "\x00\xFF\xFF\xFF\x00\x00\x00\xFF",
293
+ "\x00\xFF\xFF\xFF\x00\x00\xFF\x00", "\x00\xFF\xFF\xFF\x00\x00\xFF\xFF",
294
+ "\x00\xFF\xFF\xFF\x00\xFF\x00\x00", "\x00\xFF\xFF\xFF\x00\xFF\x00\xFF",
295
+ "\x00\xFF\xFF\xFF\x00\xFF\xFF\x00", "\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF",
296
+ "\x00\xFF\xFF\xFF\xFF\x00\x00\x00", "\x00\xFF\xFF\xFF\xFF\x00\x00\xFF",
297
+ "\x00\xFF\xFF\xFF\xFF\x00\xFF\x00", "\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF",
298
+ "\x00\xFF\xFF\xFF\xFF\xFF\x00\x00", "\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF",
299
+ "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
300
+ "\xFF\x00\x00\x00\x00\x00\x00\x00", "\xFF\x00\x00\x00\x00\x00\x00\xFF",
301
+ "\xFF\x00\x00\x00\x00\x00\xFF\x00", "\xFF\x00\x00\x00\x00\x00\xFF\xFF",
302
+ "\xFF\x00\x00\x00\x00\xFF\x00\x00", "\xFF\x00\x00\x00\x00\xFF\x00\xFF",
303
+ "\xFF\x00\x00\x00\x00\xFF\xFF\x00", "\xFF\x00\x00\x00\x00\xFF\xFF\xFF",
304
+ "\xFF\x00\x00\x00\xFF\x00\x00\x00", "\xFF\x00\x00\x00\xFF\x00\x00\xFF",
305
+ "\xFF\x00\x00\x00\xFF\x00\xFF\x00", "\xFF\x00\x00\x00\xFF\x00\xFF\xFF",
306
+ "\xFF\x00\x00\x00\xFF\xFF\x00\x00", "\xFF\x00\x00\x00\xFF\xFF\x00\xFF",
307
+ "\xFF\x00\x00\x00\xFF\xFF\xFF\x00", "\xFF\x00\x00\x00\xFF\xFF\xFF\xFF",
308
+ "\xFF\x00\x00\xFF\x00\x00\x00\x00", "\xFF\x00\x00\xFF\x00\x00\x00\xFF",
309
+ "\xFF\x00\x00\xFF\x00\x00\xFF\x00", "\xFF\x00\x00\xFF\x00\x00\xFF\xFF",
310
+ "\xFF\x00\x00\xFF\x00\xFF\x00\x00", "\xFF\x00\x00\xFF\x00\xFF\x00\xFF",
311
+ "\xFF\x00\x00\xFF\x00\xFF\xFF\x00", "\xFF\x00\x00\xFF\x00\xFF\xFF\xFF",
312
+ "\xFF\x00\x00\xFF\xFF\x00\x00\x00", "\xFF\x00\x00\xFF\xFF\x00\x00\xFF",
313
+ "\xFF\x00\x00\xFF\xFF\x00\xFF\x00", "\xFF\x00\x00\xFF\xFF\x00\xFF\xFF",
314
+ "\xFF\x00\x00\xFF\xFF\xFF\x00\x00", "\xFF\x00\x00\xFF\xFF\xFF\x00\xFF",
315
+ "\xFF\x00\x00\xFF\xFF\xFF\xFF\x00", "\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF",
316
+ "\xFF\x00\xFF\x00\x00\x00\x00\x00", "\xFF\x00\xFF\x00\x00\x00\x00\xFF",
317
+ "\xFF\x00\xFF\x00\x00\x00\xFF\x00", "\xFF\x00\xFF\x00\x00\x00\xFF\xFF",
318
+ "\xFF\x00\xFF\x00\x00\xFF\x00\x00", "\xFF\x00\xFF\x00\x00\xFF\x00\xFF",
319
+ "\xFF\x00\xFF\x00\x00\xFF\xFF\x00", "\xFF\x00\xFF\x00\x00\xFF\xFF\xFF",
320
+ "\xFF\x00\xFF\x00\xFF\x00\x00\x00", "\xFF\x00\xFF\x00\xFF\x00\x00\xFF",
321
+ "\xFF\x00\xFF\x00\xFF\x00\xFF\x00", "\xFF\x00\xFF\x00\xFF\x00\xFF\xFF",
322
+ "\xFF\x00\xFF\x00\xFF\xFF\x00\x00", "\xFF\x00\xFF\x00\xFF\xFF\x00\xFF",
323
+ "\xFF\x00\xFF\x00\xFF\xFF\xFF\x00", "\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF",
324
+ "\xFF\x00\xFF\xFF\x00\x00\x00\x00", "\xFF\x00\xFF\xFF\x00\x00\x00\xFF",
325
+ "\xFF\x00\xFF\xFF\x00\x00\xFF\x00", "\xFF\x00\xFF\xFF\x00\x00\xFF\xFF",
326
+ "\xFF\x00\xFF\xFF\x00\xFF\x00\x00", "\xFF\x00\xFF\xFF\x00\xFF\x00\xFF",
327
+ "\xFF\x00\xFF\xFF\x00\xFF\xFF\x00", "\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF",
328
+ "\xFF\x00\xFF\xFF\xFF\x00\x00\x00", "\xFF\x00\xFF\xFF\xFF\x00\x00\xFF",
329
+ "\xFF\x00\xFF\xFF\xFF\x00\xFF\x00", "\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF",
330
+ "\xFF\x00\xFF\xFF\xFF\xFF\x00\x00", "\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF",
331
+ "\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF",
332
+ "\xFF\xFF\x00\x00\x00\x00\x00\x00", "\xFF\xFF\x00\x00\x00\x00\x00\xFF",
333
+ "\xFF\xFF\x00\x00\x00\x00\xFF\x00", "\xFF\xFF\x00\x00\x00\x00\xFF\xFF",
334
+ "\xFF\xFF\x00\x00\x00\xFF\x00\x00", "\xFF\xFF\x00\x00\x00\xFF\x00\xFF",
335
+ "\xFF\xFF\x00\x00\x00\xFF\xFF\x00", "\xFF\xFF\x00\x00\x00\xFF\xFF\xFF",
336
+ "\xFF\xFF\x00\x00\xFF\x00\x00\x00", "\xFF\xFF\x00\x00\xFF\x00\x00\xFF",
337
+ "\xFF\xFF\x00\x00\xFF\x00\xFF\x00", "\xFF\xFF\x00\x00\xFF\x00\xFF\xFF",
338
+ "\xFF\xFF\x00\x00\xFF\xFF\x00\x00", "\xFF\xFF\x00\x00\xFF\xFF\x00\xFF",
339
+ "\xFF\xFF\x00\x00\xFF\xFF\xFF\x00", "\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF",
340
+ "\xFF\xFF\x00\xFF\x00\x00\x00\x00", "\xFF\xFF\x00\xFF\x00\x00\x00\xFF",
341
+ "\xFF\xFF\x00\xFF\x00\x00\xFF\x00", "\xFF\xFF\x00\xFF\x00\x00\xFF\xFF",
342
+ "\xFF\xFF\x00\xFF\x00\xFF\x00\x00", "\xFF\xFF\x00\xFF\x00\xFF\x00\xFF",
343
+ "\xFF\xFF\x00\xFF\x00\xFF\xFF\x00", "\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF",
344
+ "\xFF\xFF\x00\xFF\xFF\x00\x00\x00", "\xFF\xFF\x00\xFF\xFF\x00\x00\xFF",
345
+ "\xFF\xFF\x00\xFF\xFF\x00\xFF\x00", "\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF",
346
+ "\xFF\xFF\x00\xFF\xFF\xFF\x00\x00", "\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF",
347
+ "\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF",
348
+ "\xFF\xFF\xFF\x00\x00\x00\x00\x00", "\xFF\xFF\xFF\x00\x00\x00\x00\xFF",
349
+ "\xFF\xFF\xFF\x00\x00\x00\xFF\x00", "\xFF\xFF\xFF\x00\x00\x00\xFF\xFF",
350
+ "\xFF\xFF\xFF\x00\x00\xFF\x00\x00", "\xFF\xFF\xFF\x00\x00\xFF\x00\xFF",
351
+ "\xFF\xFF\xFF\x00\x00\xFF\xFF\x00", "\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF",
352
+ "\xFF\xFF\xFF\x00\xFF\x00\x00\x00", "\xFF\xFF\xFF\x00\xFF\x00\x00\xFF",
353
+ "\xFF\xFF\xFF\x00\xFF\x00\xFF\x00", "\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF",
354
+ "\xFF\xFF\xFF\x00\xFF\xFF\x00\x00", "\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF",
355
+ "\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF",
356
+ "\xFF\xFF\xFF\xFF\x00\x00\x00\x00", "\xFF\xFF\xFF\xFF\x00\x00\x00\xFF",
357
+ "\xFF\xFF\xFF\xFF\x00\x00\xFF\x00", "\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF",
358
+ "\xFF\xFF\xFF\xFF\x00\xFF\x00\x00", "\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF",
359
+ "\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF",
360
+ "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", "\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF",
361
+ "\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF",
362
+ "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF",
363
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
364
+ );
365
+
366
+ /**
367
+ * IP mapping helper table.
368
+ *
369
+ * Indexing this table with each source byte performs the initial bit permutation.
370
+ *
371
+ * @var array
372
+ * @access private
373
+ */
374
+ var $ipmap = array(
375
+ 0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x21, 0x31,
376
+ 0x02, 0x12, 0x03, 0x13, 0x22, 0x32, 0x23, 0x33,
377
+ 0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71,
378
+ 0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73,
379
+ 0x04, 0x14, 0x05, 0x15, 0x24, 0x34, 0x25, 0x35,
380
+ 0x06, 0x16, 0x07, 0x17, 0x26, 0x36, 0x27, 0x37,
381
+ 0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75,
382
+ 0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77,
383
+ 0x80, 0x90, 0x81, 0x91, 0xA0, 0xB0, 0xA1, 0xB1,
384
+ 0x82, 0x92, 0x83, 0x93, 0xA2, 0xB2, 0xA3, 0xB3,
385
+ 0xC0, 0xD0, 0xC1, 0xD1, 0xE0, 0xF0, 0xE1, 0xF1,
386
+ 0xC2, 0xD2, 0xC3, 0xD3, 0xE2, 0xF2, 0xE3, 0xF3,
387
+ 0x84, 0x94, 0x85, 0x95, 0xA4, 0xB4, 0xA5, 0xB5,
388
+ 0x86, 0x96, 0x87, 0x97, 0xA6, 0xB6, 0xA7, 0xB7,
389
+ 0xC4, 0xD4, 0xC5, 0xD5, 0xE4, 0xF4, 0xE5, 0xF5,
390
+ 0xC6, 0xD6, 0xC7, 0xD7, 0xE6, 0xF6, 0xE7, 0xF7,
391
+ 0x08, 0x18, 0x09, 0x19, 0x28, 0x38, 0x29, 0x39,
392
+ 0x0A, 0x1A, 0x0B, 0x1B, 0x2A, 0x3A, 0x2B, 0x3B,
393
+ 0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79,
394
+ 0x4A, 0x5A, 0x4B, 0x5B, 0x6A, 0x7A, 0x6B, 0x7B,
395
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x2C, 0x3C, 0x2D, 0x3D,
396
+ 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
397
+ 0x4C, 0x5C, 0x4D, 0x5D, 0x6C, 0x7C, 0x6D, 0x7D,
398
+ 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
399
+ 0x88, 0x98, 0x89, 0x99, 0xA8, 0xB8, 0xA9, 0xB9,
400
+ 0x8A, 0x9A, 0x8B, 0x9B, 0xAA, 0xBA, 0xAB, 0xBB,
401
+ 0xC8, 0xD8, 0xC9, 0xD9, 0xE8, 0xF8, 0xE9, 0xF9,
402
+ 0xCA, 0xDA, 0xCB, 0xDB, 0xEA, 0xFA, 0xEB, 0xFB,
403
+ 0x8C, 0x9C, 0x8D, 0x9D, 0xAC, 0xBC, 0xAD, 0xBD,
404
+ 0x8E, 0x9E, 0x8F, 0x9F, 0xAE, 0xBE, 0xAF, 0xBF,
405
+ 0xCC, 0xDC, 0xCD, 0xDD, 0xEC, 0xFC, 0xED, 0xFD,
406
+ 0xCE, 0xDE, 0xCF, 0xDF, 0xEE, 0xFE, 0xEF, 0xFF
407
+ );
408
+
409
+ /**
410
+ * Inverse IP mapping helper table.
411
+ * Indexing this table with a byte value reverses the bit order.
412
+ *
413
+ * @var array
414
+ * @access private
415
+ */
416
+ var $invipmap = array(
417
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
418
+ 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
419
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
420
+ 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
421
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
422
+ 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
423
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
424
+ 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
425
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
426
+ 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
427
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
428
+ 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
429
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
430
+ 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
431
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
432
+ 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
433
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
434
+ 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
435
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
436
+ 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
437
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
438
+ 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
439
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
440
+ 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
441
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
442
+ 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
443
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
444
+ 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
445
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
446
+ 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
447
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
448
+ 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
449
+ );
450
+
451
+ /**
452
+ * Pre-permuted S-box1
453
+ *
454
+ * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
455
+ * P table: concatenation can then be replaced by exclusive ORs.
456
+ *
457
+ * @var array
458
+ * @access private
459
+ */
460
+ var $sbox1 = array(
461
+ 0x00808200, 0x00000000, 0x00008000, 0x00808202,
462
+ 0x00808002, 0x00008202, 0x00000002, 0x00008000,
463
+ 0x00000200, 0x00808200, 0x00808202, 0x00000200,
464
+ 0x00800202, 0x00808002, 0x00800000, 0x00000002,
465
+ 0x00000202, 0x00800200, 0x00800200, 0x00008200,
466
+ 0x00008200, 0x00808000, 0x00808000, 0x00800202,
467
+ 0x00008002, 0x00800002, 0x00800002, 0x00008002,
468
+ 0x00000000, 0x00000202, 0x00008202, 0x00800000,
469
+ 0x00008000, 0x00808202, 0x00000002, 0x00808000,
470
+ 0x00808200, 0x00800000, 0x00800000, 0x00000200,
471
+ 0x00808002, 0x00008000, 0x00008200, 0x00800002,
472
+ 0x00000200, 0x00000002, 0x00800202, 0x00008202,
473
+ 0x00808202, 0x00008002, 0x00808000, 0x00800202,
474
+ 0x00800002, 0x00000202, 0x00008202, 0x00808200,
475
+ 0x00000202, 0x00800200, 0x00800200, 0x00000000,
476
+ 0x00008002, 0x00008200, 0x00000000, 0x00808002
477
+ );
478
+
479
+ /**
480
+ * Pre-permuted S-box2
481
+ *
482
+ * @var array
483
+ * @access private
484
+ */
485
+ var $sbox2 = array(
486
+ 0x40084010, 0x40004000, 0x00004000, 0x00084010,
487
+ 0x00080000, 0x00000010, 0x40080010, 0x40004010,
488
+ 0x40000010, 0x40084010, 0x40084000, 0x40000000,
489
+ 0x40004000, 0x00080000, 0x00000010, 0x40080010,
490
+ 0x00084000, 0x00080010, 0x40004010, 0x00000000,
491
+ 0x40000000, 0x00004000, 0x00084010, 0x40080000,
492
+ 0x00080010, 0x40000010, 0x00000000, 0x00084000,
493
+ 0x00004010, 0x40084000, 0x40080000, 0x00004010,
494
+ 0x00000000, 0x00084010, 0x40080010, 0x00080000,
495
+ 0x40004010, 0x40080000, 0x40084000, 0x00004000,
496
+ 0x40080000, 0x40004000, 0x00000010, 0x40084010,
497
+ 0x00084010, 0x00000010, 0x00004000, 0x40000000,
498
+ 0x00004010, 0x40084000, 0x00080000, 0x40000010,
499
+ 0x00080010, 0x40004010, 0x40000010, 0x00080010,
500
+ 0x00084000, 0x00000000, 0x40004000, 0x00004010,
501
+ 0x40000000, 0x40080010, 0x40084010, 0x00084000
502
+ );
503
+
504
+ /**
505
+ * Pre-permuted S-box3
506
+ *
507
+ * @var array
508
+ * @access private
509
+ */
510
+ var $sbox3 = array(
511
+ 0x00000104, 0x04010100, 0x00000000, 0x04010004,
512
+ 0x04000100, 0x00000000, 0x00010104, 0x04000100,
513
+ 0x00010004, 0x04000004, 0x04000004, 0x00010000,
514
+ 0x04010104, 0x00010004, 0x04010000, 0x00000104,
515
+ 0x04000000, 0x00000004, 0x04010100, 0x00000100,
516
+ 0x00010100, 0x04010000, 0x04010004, 0x00010104,
517
+ 0x04000104, 0x00010100, 0x00010000, 0x04000104,
518
+ 0x00000004, 0x04010104, 0x00000100, 0x04000000,
519
+ 0x04010100, 0x04000000, 0x00010004, 0x00000104,
520
+ 0x00010000, 0x04010100, 0x04000100, 0x00000000,
521
+ 0x00000100, 0x00010004, 0x04010104, 0x04000100,
522
+ 0x04000004, 0x00000100, 0x00000000, 0x04010004,
523
+ 0x04000104, 0x00010000, 0x04000000, 0x04010104,
524
+ 0x00000004, 0x00010104, 0x00010100, 0x04000004,
525
+ 0x04010000, 0x04000104, 0x00000104, 0x04010000,
526
+ 0x00010104, 0x00000004, 0x04010004, 0x00010100
527
+ );
528
+
529
+ /**
530
+ * Pre-permuted S-box4
531
+ *
532
+ * @var array
533
+ * @access private
534
+ */
535
+ var $sbox4 = array(
536
+ 0x80401000, 0x80001040, 0x80001040, 0x00000040,
537
+ 0x00401040, 0x80400040, 0x80400000, 0x80001000,
538
+ 0x00000000, 0x00401000, 0x00401000, 0x80401040,
539
+ 0x80000040, 0x00000000, 0x00400040, 0x80400000,
540
+ 0x80000000, 0x00001000, 0x00400000, 0x80401000,
541
+ 0x00000040, 0x00400000, 0x80001000, 0x00001040,
542
+ 0x80400040, 0x80000000, 0x00001040, 0x00400040,
543
+ 0x00001000, 0x00401040, 0x80401040, 0x80000040,
544
+ 0x00400040, 0x80400000, 0x00401000, 0x80401040,
545
+ 0x80000040, 0x00000000, 0x00000000, 0x00401000,
546
+ 0x00001040, 0x00400040, 0x80400040, 0x80000000,
547
+ 0x80401000, 0x80001040, 0x80001040, 0x00000040,
548
+ 0x80401040, 0x80000040, 0x80000000, 0x00001000,
549
+ 0x80400000, 0x80001000, 0x00401040, 0x80400040,
550
+ 0x80001000, 0x00001040, 0x00400000, 0x80401000,
551
+ 0x00000040, 0x00400000, 0x00001000, 0x00401040
552
+ );
553
+
554
+ /**
555
+ * Pre-permuted S-box5
556
+ *
557
+ * @var array
558
+ * @access private
559
+ */
560
+ var $sbox5 = array(
561
+ 0x00000080, 0x01040080, 0x01040000, 0x21000080,
562
+ 0x00040000, 0x00000080, 0x20000000, 0x01040000,
563
+ 0x20040080, 0x00040000, 0x01000080, 0x20040080,
564
+ 0x21000080, 0x21040000, 0x00040080, 0x20000000,
565
+ 0x01000000, 0x20040000, 0x20040000, 0x00000000,
566
+ 0x20000080, 0x21040080, 0x21040080, 0x01000080,
567
+ 0x21040000, 0x20000080, 0x00000000, 0x21000000,
568
+ 0x01040080, 0x01000000, 0x21000000, 0x00040080,
569
+ 0x00040000, 0x21000080, 0x00000080, 0x01000000,
570
+ 0x20000000, 0x01040000, 0x21000080, 0x20040080,
571
+ 0x01000080, 0x20000000, 0x21040000, 0x01040080,
572
+ 0x20040080, 0x00000080, 0x01000000, 0x21040000,
573
+ 0x21040080, 0x00040080, 0x21000000, 0x21040080,
574
+ 0x01040000, 0x00000000, 0x20040000, 0x21000000,
575
+ 0x00040080, 0x01000080, 0x20000080, 0x00040000,
576
+ 0x00000000, 0x20040000, 0x01040080, 0x20000080
577
+ );
578
+
579
+ /**
580
+ * Pre-permuted S-box6
581
+ *
582
+ * @var array
583
+ * @access private
584
+ */
585
+ var $sbox6 = array(
586
+ 0x10000008, 0x10200000, 0x00002000, 0x10202008,
587
+ 0x10200000, 0x00000008, 0x10202008, 0x00200000,
588
+ 0x10002000, 0x00202008, 0x00200000, 0x10000008,
589
+ 0x00200008, 0x10002000, 0x10000000, 0x00002008,
590
+ 0x00000000, 0x00200008, 0x10002008, 0x00002000,
591
+ 0x00202000, 0x10002008, 0x00000008, 0x10200008,
592
+ 0x10200008, 0x00000000, 0x00202008, 0x10202000,
593
+ 0x00002008, 0x00202000, 0x10202000, 0x10000000,
594
+ 0x10002000, 0x00000008, 0x10200008, 0x00202000,
595
+ 0x10202008, 0x00200000, 0x00002008, 0x10000008,
596
+ 0x00200000, 0x10002000, 0x10000000, 0x00002008,
597
+ 0x10000008, 0x10202008, 0x00202000, 0x10200000,
598
+ 0x00202008, 0x10202000, 0x00000000, 0x10200008,
599
+ 0x00000008, 0x00002000, 0x10200000, 0x00202008,
600
+ 0x00002000, 0x00200008, 0x10002008, 0x00000000,
601
+ 0x10202000, 0x10000000, 0x00200008, 0x10002008
602
+ );
603
+
604
+ /**
605
+ * Pre-permuted S-box7
606
+ *
607
+ * @var array
608
+ * @access private
609
+ */
610
+ var $sbox7 = array(
611
+ 0x00100000, 0x02100001, 0x02000401, 0x00000000,
612
+ 0x00000400, 0x02000401, 0x00100401, 0x02100400,
613
+ 0x02100401, 0x00100000, 0x00000000, 0x02000001,
614
+ 0x00000001, 0x02000000, 0x02100001, 0x00000401,
615
+ 0x02000400, 0x00100401, 0x00100001, 0x02000400,
616
+ 0x02000001, 0x02100000, 0x02100400, 0x00100001,
617
+ 0x02100000, 0x00000400, 0x00000401, 0x02100401,
618
+ 0x00100400, 0x00000001, 0x02000000, 0x00100400,
619
+ 0x02000000, 0x00100400, 0x00100000, 0x02000401,
620
+ 0x02000401, 0x02100001, 0x02100001, 0x00000001,
621
+ 0x00100001, 0x02000000, 0x02000400, 0x00100000,
622
+ 0x02100400, 0x00000401, 0x00100401, 0x02100400,
623
+ 0x00000401, 0x02000001, 0x02100401, 0x02100000,
624
+ 0x00100400, 0x00000000, 0x00000001, 0x02100401,
625
+ 0x00000000, 0x00100401, 0x02100000, 0x00000400,
626
+ 0x02000001, 0x02000400, 0x00000400, 0x00100001
627
+ );
628
+
629
+ /**
630
+ * Pre-permuted S-box8
631
+ *
632
+ * @var array
633
+ * @access private
634
+ */
635
+ var $sbox8 = array(
636
+ 0x08000820, 0x00000800, 0x00020000, 0x08020820,
637
+ 0x08000000, 0x08000820, 0x00000020, 0x08000000,
638
+ 0x00020020, 0x08020000, 0x08020820, 0x00020800,
639
+ 0x08020800, 0x00020820, 0x00000800, 0x00000020,
640
+ 0x08020000, 0x08000020, 0x08000800, 0x00000820,
641
+ 0x00020800, 0x00020020, 0x08020020, 0x08020800,
642
+ 0x00000820, 0x00000000, 0x00000000, 0x08020020,
643
+ 0x08000020, 0x08000800, 0x00020820, 0x00020000,
644
+ 0x00020820, 0x00020000, 0x08020800, 0x00000800,
645
+ 0x00000020, 0x08020020, 0x00000800, 0x00020820,
646
+ 0x08000800, 0x00000020, 0x08000020, 0x08020000,
647
+ 0x08020020, 0x08000000, 0x00020000, 0x08000820,
648
+ 0x00000000, 0x08020820, 0x00020020, 0x08000020,
649
+ 0x08020000, 0x08000800, 0x08000820, 0x00000000,
650
+ 0x08020820, 0x00020800, 0x00020800, 0x00000820,
651
+ 0x00000820, 0x00020020, 0x08000000, 0x08020800
652
+ );
653
+
654
+ /**
655
+ * Test for engine validity
656
+ *
657
+ * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
658
+ *
659
+ * @see Crypt_Base::isValidEngine()
660
+ * @param int $engine
661
+ * @access public
662
+ * @return bool
663
+ */
664
+ function isValidEngine($engine)
665
+ {
666
+ if ($this->key_length_max == 8) {
667
+ if ($engine == CRYPT_ENGINE_OPENSSL) {
668
+ $this->cipher_name_openssl_ecb = 'des-ecb';
669
+ $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
670
+ }
671
+ }
672
+
673
+ return parent::isValidEngine($engine);
674
+ }
675
+
676
+ /**
677
+ * Sets the key.
678
+ *
679
+ * Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
680
+ * only use the first eight, if $key has more then eight characters in it, and pad $key with the
681
+ * null byte if it is less then eight characters long.
682
+ *
683
+ * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
684
+ *
685
+ * If the key is not explicitly set, it'll be assumed to be all zero's.
686
+ *
687
+ * @see Crypt_Base::setKey()
688
+ * @access public
689
+ * @param string $key
690
+ */
691
+ function setKey($key)
692
+ {
693
+ // We check/cut here only up to max length of the key.
694
+ // Key padding to the proper length will be done in _setupKey()
695
+ if (strlen($key) > $this->key_length_max) {
696
+ $key = substr($key, 0, $this->key_length_max);
697
+ }
698
+
699
+ // Sets the key
700
+ parent::setKey($key);
701
+ }
702
+
703
+ /**
704
+ * Encrypts a block
705
+ *
706
+ * @see Crypt_Base::_encryptBlock()
707
+ * @see Crypt_Base::encrypt()
708
+ * @see self::encrypt()
709
+ * @access private
710
+ * @param string $in
711
+ * @return string
712
+ */
713
+ function _encryptBlock($in)
714
+ {
715
+ return $this->_processBlock($in, CRYPT_DES_ENCRYPT);
716
+ }
717
+
718
+ /**
719
+ * Decrypts a block
720
+ *
721
+ * @see Crypt_Base::_decryptBlock()
722
+ * @see Crypt_Base::decrypt()
723
+ * @see self::decrypt()
724
+ * @access private
725
+ * @param string $in
726
+ * @return string
727
+ */
728
+ function _decryptBlock($in)
729
+ {
730
+ return $this->_processBlock($in, CRYPT_DES_DECRYPT);
731
+ }
732
+
733
+ /**
734
+ * Encrypts or decrypts a 64-bit block
735
+ *
736
+ * $mode should be either CRYPT_DES_ENCRYPT or CRYPT_DES_DECRYPT. See
737
+ * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
738
+ * idea of what this function does.
739
+ *
740
+ * @see self::_encryptBlock()
741
+ * @see self::_decryptBlock()
742
+ * @access private
743
+ * @param string $block
744
+ * @param int $mode
745
+ * @return string
746
+ */
747
+ function _processBlock($block, $mode)
748
+ {
749
+ static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
750
+ if (!$sbox1) {
751
+ $sbox1 = array_map("intval", $this->sbox1);
752
+ $sbox2 = array_map("intval", $this->sbox2);
753
+ $sbox3 = array_map("intval", $this->sbox3);
754
+ $sbox4 = array_map("intval", $this->sbox4);
755
+ $sbox5 = array_map("intval", $this->sbox5);
756
+ $sbox6 = array_map("intval", $this->sbox6);
757
+ $sbox7 = array_map("intval", $this->sbox7);
758
+ $sbox8 = array_map("intval", $this->sbox8);
759
+ /* Merge $shuffle with $[inv]ipmap */
760
+ for ($i = 0; $i < 256; ++$i) {
761
+ $shuffleip[] = $this->shuffle[$this->ipmap[$i]];
762
+ $shuffleinvip[] = $this->shuffle[$this->invipmap[$i]];
763
+ }
764
+ }
765
+
766
+ $keys = $this->keys[$mode];
767
+ $ki = -1;
768
+
769
+ // Do the initial IP permutation.
770
+ $t = unpack('Nl/Nr', $block);
771
+ list($l, $r) = array($t['l'], $t['r']);
772
+ $block = ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
773
+ ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
774
+ ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
775
+ ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
776
+ ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
777
+ ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
778
+ ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
779
+ ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
780
+
781
+ // Extract L0 and R0.
782
+ $t = unpack('Nl/Nr', $block);
783
+ list($l, $r) = array($t['l'], $t['r']);
784
+
785
+ for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
786
+ // Perform the 16 steps.
787
+ for ($i = 0; $i < 16; $i++) {
788
+ // start of "the Feistel (F) function" - see the following URL:
789
+ // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
790
+ // Merge key schedule.
791
+ $b1 = (($r >> 3) & 0x1FFFFFFF) ^ ($r << 29) ^ $keys[++$ki];
792
+ $b2 = (($r >> 31) & 0x00000001) ^ ($r << 1) ^ $keys[++$ki];
793
+
794
+ // S-box indexing.
795
+ $t = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
796
+ $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
797
+ $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^
798
+ $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ $l;
799
+ // end of "the Feistel (F) function"
800
+
801
+ $l = $r;
802
+ $r = $t;
803
+ }
804
+
805
+ // Last step should not permute L & R.
806
+ $t = $l;
807
+ $l = $r;
808
+ $r = $t;
809
+ }
810
+
811
+ // Perform the inverse IP permutation.
812
+ return ($shuffleinvip[($r >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
813
+ ($shuffleinvip[($l >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
814
+ ($shuffleinvip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
815
+ ($shuffleinvip[($l >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
816
+ ($shuffleinvip[($r >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
817
+ ($shuffleinvip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
818
+ ($shuffleinvip[ $r & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
819
+ ($shuffleinvip[ $l & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
820
+ }
821
+
822
+ /**
823
+ * Creates the key schedule
824
+ *
825
+ * @see Crypt_Base::_setupKey()
826
+ * @access private
827
+ */
828
+ function _setupKey()
829
+ {
830
+ if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) {
831
+ // already expanded
832
+ return;
833
+ }
834
+ $this->kl = array('key' => $this->key, 'des_rounds' => $this->des_rounds);
835
+
836
+ static $shifts = array( // number of key bits shifted per round
837
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
838
+ );
839
+
840
+ static $pc1map = array(
841
+ 0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C,
842
+ 0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E,
843
+ 0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1C, 0x1C,
844
+ 0x12, 0x12, 0x1A, 0x1A, 0x16, 0x16, 0x1E, 0x1E,
845
+ 0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2C, 0x2C,
846
+ 0x22, 0x22, 0x2A, 0x2A, 0x26, 0x26, 0x2E, 0x2E,
847
+ 0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3C, 0x3C,
848
+ 0x32, 0x32, 0x3A, 0x3A, 0x36, 0x36, 0x3E, 0x3E,
849
+ 0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4C, 0x4C,
850
+ 0x42, 0x42, 0x4A, 0x4A, 0x46, 0x46, 0x4E, 0x4E,
851
+ 0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5C, 0x5C,
852
+ 0x52, 0x52, 0x5A, 0x5A, 0x56, 0x56, 0x5E, 0x5E,
853
+ 0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6C, 0x6C,
854
+ 0x62, 0x62, 0x6A, 0x6A, 0x66, 0x66, 0x6E, 0x6E,
855
+ 0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7C, 0x7C,
856
+ 0x72, 0x72, 0x7A, 0x7A, 0x76, 0x76, 0x7E, 0x7E,
857
+ 0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8C, 0x8C,
858
+ 0x82, 0x82, 0x8A, 0x8A, 0x86, 0x86, 0x8E, 0x8E,
859
+ 0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9C, 0x9C,
860
+ 0x92, 0x92, 0x9A, 0x9A, 0x96, 0x96, 0x9E, 0x9E,
861
+ 0xA0, 0xA0, 0xA8, 0xA8, 0xA4, 0xA4, 0xAC, 0xAC,
862
+ 0xA2, 0xA2, 0xAA, 0xAA, 0xA6, 0xA6, 0xAE, 0xAE,
863
+ 0xB0, 0xB0, 0xB8, 0xB8, 0xB4, 0xB4, 0xBC, 0xBC,
864
+ 0xB2, 0xB2, 0xBA, 0xBA, 0xB6, 0xB6, 0xBE, 0xBE,
865
+ 0xC0, 0xC0, 0xC8, 0xC8, 0xC4, 0xC4, 0xCC, 0xCC,
866
+ 0xC2, 0xC2, 0xCA, 0xCA, 0xC6, 0xC6, 0xCE, 0xCE,
867
+ 0xD0, 0xD0, 0xD8, 0xD8, 0xD4, 0xD4, 0xDC, 0xDC,
868
+ 0xD2, 0xD2, 0xDA, 0xDA, 0xD6, 0xD6, 0xDE, 0xDE,
869
+ 0xE0, 0xE0, 0xE8, 0xE8, 0xE4, 0xE4, 0xEC, 0xEC,
870
+ 0xE2, 0xE2, 0xEA, 0xEA, 0xE6, 0xE6, 0xEE, 0xEE,
871
+ 0xF0, 0xF0, 0xF8, 0xF8, 0xF4, 0xF4, 0xFC, 0xFC,
872
+ 0xF2, 0xF2, 0xFA, 0xFA, 0xF6, 0xF6, 0xFE, 0xFE
873
+ );
874
+
875
+ // Mapping tables for the PC-2 transformation.
876
+ static $pc2mapc1 = array(
877
+ 0x00000000, 0x00000400, 0x00200000, 0x00200400,
878
+ 0x00000001, 0x00000401, 0x00200001, 0x00200401,
879
+ 0x02000000, 0x02000400, 0x02200000, 0x02200400,
880
+ 0x02000001, 0x02000401, 0x02200001, 0x02200401
881
+ );
882
+ static $pc2mapc2 = array(
883
+ 0x00000000, 0x00000800, 0x08000000, 0x08000800,
884
+ 0x00010000, 0x00010800, 0x08010000, 0x08010800,
885
+ 0x00000000, 0x00000800, 0x08000000, 0x08000800,
886
+ 0x00010000, 0x00010800, 0x08010000, 0x08010800,
887
+ 0x00000100, 0x00000900, 0x08000100, 0x08000900,
888
+ 0x00010100, 0x00010900, 0x08010100, 0x08010900,
889
+ 0x00000100, 0x00000900, 0x08000100, 0x08000900,
890
+ 0x00010100, 0x00010900, 0x08010100, 0x08010900,
891
+ 0x00000010, 0x00000810, 0x08000010, 0x08000810,
892
+ 0x00010010, 0x00010810, 0x08010010, 0x08010810,
893
+ 0x00000010, 0x00000810, 0x08000010, 0x08000810,
894
+ 0x00010010, 0x00010810, 0x08010010, 0x08010810,
895
+ 0x00000110, 0x00000910, 0x08000110, 0x08000910,
896
+ 0x00010110, 0x00010910, 0x08010110, 0x08010910,
897
+ 0x00000110, 0x00000910, 0x08000110, 0x08000910,
898
+ 0x00010110, 0x00010910, 0x08010110, 0x08010910,
899
+ 0x00040000, 0x00040800, 0x08040000, 0x08040800,
900
+ 0x00050000, 0x00050800, 0x08050000, 0x08050800,
901
+ 0x00040000, 0x00040800, 0x08040000, 0x08040800,
902
+ 0x00050000, 0x00050800, 0x08050000, 0x08050800,
903
+ 0x00040100, 0x00040900, 0x08040100, 0x08040900,
904
+ 0x00050100, 0x00050900, 0x08050100, 0x08050900,
905
+ 0x00040100, 0x00040900, 0x08040100, 0x08040900,
906
+ 0x00050100, 0x00050900, 0x08050100, 0x08050900,
907
+ 0x00040010, 0x00040810, 0x08040010, 0x08040810,
908
+ 0x00050010, 0x00050810, 0x08050010, 0x08050810,
909
+ 0x00040010, 0x00040810, 0x08040010, 0x08040810,
910
+ 0x00050010, 0x00050810, 0x08050010, 0x08050810,
911
+ 0x00040110, 0x00040910, 0x08040110, 0x08040910,
912
+ 0x00050110, 0x00050910, 0x08050110, 0x08050910,
913
+ 0x00040110, 0x00040910, 0x08040110, 0x08040910,
914
+ 0x00050110, 0x00050910, 0x08050110, 0x08050910,
915
+ 0x01000000, 0x01000800, 0x09000000, 0x09000800,
916
+ 0x01010000, 0x01010800, 0x09010000, 0x09010800,
917
+ 0x01000000, 0x01000800, 0x09000000, 0x09000800,
918
+ 0x01010000, 0x01010800, 0x09010000, 0x09010800,
919
+ 0x01000100, 0x01000900, 0x09000100, 0x09000900,
920
+ 0x01010100, 0x01010900, 0x09010100, 0x09010900,
921
+ 0x01000100, 0x01000900, 0x09000100, 0x09000900,
922
+ 0x01010100, 0x01010900, 0x09010100, 0x09010900,
923
+ 0x01000010, 0x01000810, 0x09000010, 0x09000810,
924
+ 0x01010010, 0x01010810, 0x09010010, 0x09010810,
925
+ 0x01000010, 0x01000810, 0x09000010, 0x09000810,
926
+ 0x01010010, 0x01010810, 0x09010010, 0x09010810,
927
+ 0x01000110, 0x01000910, 0x09000110, 0x09000910,
928
+ 0x01010110, 0x01010910, 0x09010110, 0x09010910,
929
+ 0x01000110, 0x01000910, 0x09000110, 0x09000910,
930
+ 0x01010110, 0x01010910, 0x09010110, 0x09010910,
931
+ 0x01040000, 0x01040800, 0x09040000, 0x09040800,
932
+ 0x01050000, 0x01050800, 0x09050000, 0x09050800,
933
+ 0x01040000, 0x01040800, 0x09040000, 0x09040800,
934
+ 0x01050000, 0x01050800, 0x09050000, 0x09050800,
935
+ 0x01040100, 0x01040900, 0x09040100, 0x09040900,
936
+ 0x01050100, 0x01050900, 0x09050100, 0x09050900,
937
+ 0x01040100, 0x01040900, 0x09040100, 0x09040900,
938
+ 0x01050100, 0x01050900, 0x09050100, 0x09050900,
939
+ 0x01040010, 0x01040810, 0x09040010, 0x09040810,
940
+ 0x01050010, 0x01050810, 0x09050010, 0x09050810,
941
+ 0x01040010, 0x01040810, 0x09040010, 0x09040810,
942
+ 0x01050010, 0x01050810, 0x09050010, 0x09050810,
943
+ 0x01040110, 0x01040910, 0x09040110, 0x09040910,
944
+ 0x01050110, 0x01050910, 0x09050110, 0x09050910,
945
+ 0x01040110, 0x01040910, 0x09040110, 0x09040910,
946
+ 0x01050110, 0x01050910, 0x09050110, 0x09050910
947
+ );
948
+ static $pc2mapc3 = array(
949
+ 0x00000000, 0x00000004, 0x00001000, 0x00001004,
950
+ 0x00000000, 0x00000004, 0x00001000, 0x00001004,
951
+ 0x10000000, 0x10000004, 0x10001000, 0x10001004,
952
+ 0x10000000, 0x10000004, 0x10001000, 0x10001004,
953
+ 0x00000020, 0x00000024, 0x00001020, 0x00001024,
954
+ 0x00000020, 0x00000024, 0x00001020, 0x00001024,
955
+ 0x10000020, 0x10000024, 0x10001020, 0x10001024,
956
+ 0x10000020, 0x10000024, 0x10001020, 0x10001024,
957
+ 0x00080000, 0x00080004, 0x00081000, 0x00081004,
958
+ 0x00080000, 0x00080004, 0x00081000, 0x00081004,
959
+ 0x10080000, 0x10080004, 0x10081000, 0x10081004,
960
+ 0x10080000, 0x10080004, 0x10081000, 0x10081004,
961
+ 0x00080020, 0x00080024, 0x00081020, 0x00081024,
962
+ 0x00080020, 0x00080024, 0x00081020, 0x00081024,
963
+ 0x10080020, 0x10080024, 0x10081020, 0x10081024,
964
+ 0x10080020, 0x10080024, 0x10081020, 0x10081024,
965
+ 0x20000000, 0x20000004, 0x20001000, 0x20001004,
966
+ 0x20000000, 0x20000004, 0x20001000, 0x20001004,
967
+ 0x30000000, 0x30000004, 0x30001000, 0x30001004,
968
+ 0x30000000, 0x30000004, 0x30001000, 0x30001004,
969
+ 0x20000020, 0x20000024, 0x20001020, 0x20001024,
970
+ 0x20000020, 0x20000024, 0x20001020, 0x20001024,
971
+ 0x30000020, 0x30000024, 0x30001020, 0x30001024,
972
+ 0x30000020, 0x30000024, 0x30001020, 0x30001024,
973
+ 0x20080000, 0x20080004, 0x20081000, 0x20081004,
974
+ 0x20080000, 0x20080004, 0x20081000, 0x20081004,
975
+ 0x30080000, 0x30080004, 0x30081000, 0x30081004,
976
+ 0x30080000, 0x30080004, 0x30081000, 0x30081004,
977
+ 0x20080020, 0x20080024, 0x20081020, 0x20081024,
978
+ 0x20080020, 0x20080024, 0x20081020, 0x20081024,
979
+ 0x30080020, 0x30080024, 0x30081020, 0x30081024,
980
+ 0x30080020, 0x30080024, 0x30081020, 0x30081024,
981
+ 0x00000002, 0x00000006, 0x00001002, 0x00001006,
982
+ 0x00000002, 0x00000006, 0x00001002, 0x00001006,
983
+ 0x10000002, 0x10000006, 0x10001002, 0x10001006,
984
+ 0x10000002, 0x10000006, 0x10001002, 0x10001006,
985
+ 0x00000022, 0x00000026, 0x00001022, 0x00001026,
986
+ 0x00000022, 0x00000026, 0x00001022, 0x00001026,
987
+ 0x10000022, 0x10000026, 0x10001022, 0x10001026,
988
+ 0x10000022, 0x10000026, 0x10001022, 0x10001026,
989
+ 0x00080002, 0x00080006, 0x00081002, 0x00081006,
990
+ 0x00080002, 0x00080006, 0x00081002, 0x00081006,
991
+ 0x10080002, 0x10080006, 0x10081002, 0x10081006,
992
+ 0x10080002, 0x10080006, 0x10081002, 0x10081006,
993
+ 0x00080022, 0x00080026, 0x00081022, 0x00081026,
994
+ 0x00080022, 0x00080026, 0x00081022, 0x00081026,
995
+ 0x10080022, 0x10080026, 0x10081022, 0x10081026,
996
+ 0x10080022, 0x10080026, 0x10081022, 0x10081026,
997
+ 0x20000002, 0x20000006, 0x20001002, 0x20001006,
998
+ 0x20000002, 0x20000006, 0x20001002, 0x20001006,
999
+ 0x30000002, 0x30000006, 0x30001002, 0x30001006,
1000
+ 0x30000002, 0x30000006, 0x30001002, 0x30001006,
1001
+ 0x20000022, 0x20000026, 0x20001022, 0x20001026,
1002
+ 0x20000022, 0x20000026, 0x20001022, 0x20001026,
1003
+ 0x30000022, 0x30000026, 0x30001022, 0x30001026,
1004
+ 0x30000022, 0x30000026, 0x30001022, 0x30001026,
1005
+ 0x20080002, 0x20080006, 0x20081002, 0x20081006,
1006
+ 0x20080002, 0x20080006, 0x20081002, 0x20081006,
1007
+ 0x30080002, 0x30080006, 0x30081002, 0x30081006,
1008
+ 0x30080002, 0x30080006, 0x30081002, 0x30081006,
1009
+ 0x20080022, 0x20080026, 0x20081022, 0x20081026,
1010
+ 0x20080022, 0x20080026, 0x20081022, 0x20081026,
1011
+ 0x30080022, 0x30080026, 0x30081022, 0x30081026,
1012
+ 0x30080022, 0x30080026, 0x30081022, 0x30081026
1013
+ );
1014
+ static $pc2mapc4 = array(
1015
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
1016
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
1017
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
1018
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
1019
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
1020
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
1021
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
1022
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
1023
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
1024
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
1025
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
1026
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
1027
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
1028
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
1029
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
1030
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
1031
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
1032
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
1033
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
1034
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
1035
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
1036
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
1037
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
1038
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
1039
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
1040
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
1041
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
1042
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
1043
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
1044
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
1045
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
1046
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
1047
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
1048
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
1049
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
1050
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
1051
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
1052
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
1053
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
1054
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
1055
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
1056
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
1057
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
1058
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
1059
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
1060
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208,
1061
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
1062
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208,
1063
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
1064
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
1065
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
1066
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
1067
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
1068
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
1069
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
1070
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
1071
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
1072
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
1073
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
1074
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
1075
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
1076
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208,
1077
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
1078
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208
1079
+ );
1080
+ static $pc2mapd1 = array(
1081
+ 0x00000000, 0x00000001, 0x08000000, 0x08000001,
1082
+ 0x00200000, 0x00200001, 0x08200000, 0x08200001,
1083
+ 0x00000002, 0x00000003, 0x08000002, 0x08000003,
1084
+ 0x00200002, 0x00200003, 0x08200002, 0x08200003
1085
+ );
1086
+ static $pc2mapd2 = array(
1087
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
1088
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
1089
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
1090
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
1091
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
1092
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
1093
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
1094
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
1095
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
1096
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
1097
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
1098
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
1099
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
1100
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
1101
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
1102
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
1103
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1104
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1105
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1106
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1107
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1108
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1109
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1110
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1111
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1112
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
1113
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1114
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
1115
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1116
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
1117
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1118
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
1119
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
1120
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
1121
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
1122
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
1123
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
1124
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
1125
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
1126
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
1127
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
1128
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
1129
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
1130
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
1131
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
1132
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
1133
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
1134
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
1135
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1136
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1137
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1138
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1139
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1140
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1141
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
1142
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
1143
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1144
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
1145
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1146
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
1147
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1148
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
1149
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
1150
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04
1151
+ );
1152
+ static $pc2mapd3 = array(
1153
+ 0x00000000, 0x00010000, 0x02000000, 0x02010000,
1154
+ 0x00000020, 0x00010020, 0x02000020, 0x02010020,
1155
+ 0x00040000, 0x00050000, 0x02040000, 0x02050000,
1156
+ 0x00040020, 0x00050020, 0x02040020, 0x02050020,
1157
+ 0x00002000, 0x00012000, 0x02002000, 0x02012000,
1158
+ 0x00002020, 0x00012020, 0x02002020, 0x02012020,
1159
+ 0x00042000, 0x00052000, 0x02042000, 0x02052000,
1160
+ 0x00042020, 0x00052020, 0x02042020, 0x02052020,
1161
+ 0x00000000, 0x00010000, 0x02000000, 0x02010000,
1162
+ 0x00000020, 0x00010020, 0x02000020, 0x02010020,
1163
+ 0x00040000, 0x00050000, 0x02040000, 0x02050000,
1164
+ 0x00040020, 0x00050020, 0x02040020, 0x02050020,
1165
+ 0x00002000, 0x00012000, 0x02002000, 0x02012000,
1166
+ 0x00002020, 0x00012020, 0x02002020, 0x02012020,
1167
+ 0x00042000, 0x00052000, 0x02042000, 0x02052000,
1168
+ 0x00042020, 0x00052020, 0x02042020, 0x02052020,
1169
+ 0x00000010, 0x00010010, 0x02000010, 0x02010010,
1170
+ 0x00000030, 0x00010030, 0x02000030, 0x02010030,
1171
+ 0x00040010, 0x00050010, 0x02040010, 0x02050010,
1172
+ 0x00040030, 0x00050030, 0x02040030, 0x02050030,
1173
+ 0x00002010, 0x00012010, 0x02002010, 0x02012010,
1174
+ 0x00002030, 0x00012030, 0x02002030, 0x02012030,
1175
+ 0x00042010, 0x00052010, 0x02042010, 0x02052010,
1176
+ 0x00042030, 0x00052030, 0x02042030, 0x02052030,
1177
+ 0x00000010, 0x00010010, 0x02000010, 0x02010010,
1178
+ 0x00000030, 0x00010030, 0x02000030, 0x02010030,
1179
+ 0x00040010, 0x00050010, 0x02040010, 0x02050010,
1180
+ 0x00040030, 0x00050030, 0x02040030, 0x02050030,
1181
+ 0x00002010, 0x00012010, 0x02002010, 0x02012010,
1182
+ 0x00002030, 0x00012030, 0x02002030, 0x02012030,
1183
+ 0x00042010, 0x00052010, 0x02042010, 0x02052010,
1184
+ 0x00042030, 0x00052030, 0x02042030, 0x02052030,
1185
+ 0x20000000, 0x20010000, 0x22000000, 0x22010000,
1186
+ 0x20000020, 0x20010020, 0x22000020, 0x22010020,
1187
+ 0x20040000, 0x20050000, 0x22040000, 0x22050000,
1188
+ 0x20040020, 0x20050020, 0x22040020, 0x22050020,
1189
+ 0x20002000, 0x20012000, 0x22002000, 0x22012000,
1190
+ 0x20002020, 0x20012020, 0x22002020, 0x22012020,
1191
+ 0x20042000, 0x20052000, 0x22042000, 0x22052000,
1192
+ 0x20042020, 0x20052020, 0x22042020, 0x22052020,
1193
+ 0x20000000, 0x20010000, 0x22000000, 0x22010000,
1194
+ 0x20000020, 0x20010020, 0x22000020, 0x22010020,
1195
+ 0x20040000, 0x20050000, 0x22040000, 0x22050000,
1196
+ 0x20040020, 0x20050020, 0x22040020, 0x22050020,
1197
+ 0x20002000, 0x20012000, 0x22002000, 0x22012000,
1198
+ 0x20002020, 0x20012020, 0x22002020, 0x22012020,
1199
+ 0x20042000, 0x20052000, 0x22042000, 0x22052000,
1200
+ 0x20042020, 0x20052020, 0x22042020, 0x22052020,
1201
+ 0x20000010, 0x20010010, 0x22000010, 0x22010010,
1202
+ 0x20000030, 0x20010030, 0x22000030, 0x22010030,
1203
+ 0x20040010, 0x20050010, 0x22040010, 0x22050010,
1204
+ 0x20040030, 0x20050030, 0x22040030, 0x22050030,
1205
+ 0x20002010, 0x20012010, 0x22002010, 0x22012010,
1206
+ 0x20002030, 0x20012030, 0x22002030, 0x22012030,
1207
+ 0x20042010, 0x20052010, 0x22042010, 0x22052010,
1208
+ 0x20042030, 0x20052030, 0x22042030, 0x22052030,
1209
+ 0x20000010, 0x20010010, 0x22000010, 0x22010010,
1210
+ 0x20000030, 0x20010030, 0x22000030, 0x22010030,
1211
+ 0x20040010, 0x20050010, 0x22040010, 0x22050010,
1212
+ 0x20040030, 0x20050030, 0x22040030, 0x22050030,
1213
+ 0x20002010, 0x20012010, 0x22002010, 0x22012010,
1214
+ 0x20002030, 0x20012030, 0x22002030, 0x22012030,
1215
+ 0x20042010, 0x20052010, 0x22042010, 0x22052010,
1216
+ 0x20042030, 0x20052030, 0x22042030, 0x22052030
1217
+ );
1218
+ static $pc2mapd4 = array(
1219
+ 0x00000000, 0x00000400, 0x01000000, 0x01000400,
1220
+ 0x00000000, 0x00000400, 0x01000000, 0x01000400,
1221
+ 0x00000100, 0x00000500, 0x01000100, 0x01000500,
1222
+ 0x00000100, 0x00000500, 0x01000100, 0x01000500,
1223
+ 0x10000000, 0x10000400, 0x11000000, 0x11000400,
1224
+ 0x10000000, 0x10000400, 0x11000000, 0x11000400,
1225
+ 0x10000100, 0x10000500, 0x11000100, 0x11000500,
1226
+ 0x10000100, 0x10000500, 0x11000100, 0x11000500,
1227
+ 0x00080000, 0x00080400, 0x01080000, 0x01080400,
1228
+ 0x00080000, 0x00080400, 0x01080000, 0x01080400,
1229
+ 0x00080100, 0x00080500, 0x01080100, 0x01080500,
1230
+ 0x00080100, 0x00080500, 0x01080100, 0x01080500,
1231
+ 0x10080000, 0x10080400, 0x11080000, 0x11080400,
1232
+ 0x10080000, 0x10080400, 0x11080000, 0x11080400,
1233
+ 0x10080100, 0x10080500, 0x11080100, 0x11080500,
1234
+ 0x10080100, 0x10080500, 0x11080100, 0x11080500,
1235
+ 0x00000008, 0x00000408, 0x01000008, 0x01000408,
1236
+ 0x00000008, 0x00000408, 0x01000008, 0x01000408,
1237
+ 0x00000108, 0x00000508, 0x01000108, 0x01000508,
1238
+ 0x00000108, 0x00000508, 0x01000108, 0x01000508,
1239
+ 0x10000008, 0x10000408, 0x11000008, 0x11000408,
1240
+ 0x10000008, 0x10000408, 0x11000008, 0x11000408,
1241
+ 0x10000108, 0x10000508, 0x11000108, 0x11000508,
1242
+ 0x10000108, 0x10000508, 0x11000108, 0x11000508,
1243
+ 0x00080008, 0x00080408, 0x01080008, 0x01080408,
1244
+ 0x00080008, 0x00080408, 0x01080008, 0x01080408,
1245
+ 0x00080108, 0x00080508, 0x01080108, 0x01080508,
1246
+ 0x00080108, 0x00080508, 0x01080108, 0x01080508,
1247
+ 0x10080008, 0x10080408, 0x11080008, 0x11080408,
1248
+ 0x10080008, 0x10080408, 0x11080008, 0x11080408,
1249
+ 0x10080108, 0x10080508, 0x11080108, 0x11080508,
1250
+ 0x10080108, 0x10080508, 0x11080108, 0x11080508,
1251
+ 0x00001000, 0x00001400, 0x01001000, 0x01001400,
1252
+ 0x00001000, 0x00001400, 0x01001000, 0x01001400,
1253
+ 0x00001100, 0x00001500, 0x01001100, 0x01001500,
1254
+ 0x00001100, 0x00001500, 0x01001100, 0x01001500,
1255
+ 0x10001000, 0x10001400, 0x11001000, 0x11001400,
1256
+ 0x10001000, 0x10001400, 0x11001000, 0x11001400,
1257
+ 0x10001100, 0x10001500, 0x11001100, 0x11001500,
1258
+ 0x10001100, 0x10001500, 0x11001100, 0x11001500,
1259
+ 0x00081000, 0x00081400, 0x01081000, 0x01081400,
1260
+ 0x00081000, 0x00081400, 0x01081000, 0x01081400,
1261
+ 0x00081100, 0x00081500, 0x01081100, 0x01081500,
1262
+ 0x00081100, 0x00081500, 0x01081100, 0x01081500,
1263
+ 0x10081000, 0x10081400, 0x11081000, 0x11081400,
1264
+ 0x10081000, 0x10081400, 0x11081000, 0x11081400,
1265
+ 0x10081100, 0x10081500, 0x11081100, 0x11081500,
1266
+ 0x10081100, 0x10081500, 0x11081100, 0x11081500,
1267
+ 0x00001008, 0x00001408, 0x01001008, 0x01001408,
1268
+ 0x00001008, 0x00001408, 0x01001008, 0x01001408,
1269
+ 0x00001108, 0x00001508, 0x01001108, 0x01001508,
1270
+ 0x00001108, 0x00001508, 0x01001108, 0x01001508,
1271
+ 0x10001008, 0x10001408, 0x11001008, 0x11001408,
1272
+ 0x10001008, 0x10001408, 0x11001008, 0x11001408,
1273
+ 0x10001108, 0x10001508, 0x11001108, 0x11001508,
1274
+ 0x10001108, 0x10001508, 0x11001108, 0x11001508,
1275
+ 0x00081008, 0x00081408, 0x01081008, 0x01081408,
1276
+ 0x00081008, 0x00081408, 0x01081008, 0x01081408,
1277
+ 0x00081108, 0x00081508, 0x01081108, 0x01081508,
1278
+ 0x00081108, 0x00081508, 0x01081108, 0x01081508,
1279
+ 0x10081008, 0x10081408, 0x11081008, 0x11081408,
1280
+ 0x10081008, 0x10081408, 0x11081008, 0x11081408,
1281
+ 0x10081108, 0x10081508, 0x11081108, 0x11081508,
1282
+ 0x10081108, 0x10081508, 0x11081108, 0x11081508
1283
+ );
1284
+
1285
+ $keys = array();
1286
+ for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
1287
+ // pad the key and remove extra characters as appropriate.
1288
+ $key = str_pad(substr($this->key, $des_round * 8, 8), 8, "\0");
1289
+
1290
+ // Perform the PC/1 transformation and compute C and D.
1291
+ $t = unpack('Nl/Nr', $key);
1292
+ list($l, $r) = array($t['l'], $t['r']);
1293
+ $key = ($this->shuffle[$pc1map[ $r & 0xFF]] & "\x80\x80\x80\x80\x80\x80\x80\x00") |
1294
+ ($this->shuffle[$pc1map[($r >> 8) & 0xFF]] & "\x40\x40\x40\x40\x40\x40\x40\x00") |
1295
+ ($this->shuffle[$pc1map[($r >> 16) & 0xFF]] & "\x20\x20\x20\x20\x20\x20\x20\x00") |
1296
+ ($this->shuffle[$pc1map[($r >> 24) & 0xFF]] & "\x10\x10\x10\x10\x10\x10\x10\x00") |
1297
+ ($this->shuffle[$pc1map[ $l & 0xFF]] & "\x08\x08\x08\x08\x08\x08\x08\x00") |
1298
+ ($this->shuffle[$pc1map[($l >> 8) & 0xFF]] & "\x04\x04\x04\x04\x04\x04\x04\x00") |
1299
+ ($this->shuffle[$pc1map[($l >> 16) & 0xFF]] & "\x02\x02\x02\x02\x02\x02\x02\x00") |
1300
+ ($this->shuffle[$pc1map[($l >> 24) & 0xFF]] & "\x01\x01\x01\x01\x01\x01\x01\x00");
1301
+ $key = unpack('Nc/Nd', $key);
1302
+ $c = ( $key['c'] >> 4) & 0x0FFFFFFF;
1303
+ $d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F);
1304
+
1305
+ $keys[$des_round] = array(
1306
+ CRYPT_DES_ENCRYPT => array(),
1307
+ CRYPT_DES_DECRYPT => array_fill(0, 32, 0)
1308
+ );
1309
+ for ($i = 0, $ki = 31; $i < 16; ++$i, $ki-= 2) {
1310
+ $c <<= $shifts[$i];
1311
+ $c = ($c | ($c >> 28)) & 0x0FFFFFFF;
1312
+ $d <<= $shifts[$i];
1313
+ $d = ($d | ($d >> 28)) & 0x0FFFFFFF;
1314
+
1315
+ // Perform the PC-2 transformation.
1316
+ $cp = $pc2mapc1[ $c >> 24 ] | $pc2mapc2[($c >> 16) & 0xFF] |
1317
+ $pc2mapc3[($c >> 8) & 0xFF] | $pc2mapc4[ $c & 0xFF];
1318
+ $dp = $pc2mapd1[ $d >> 24 ] | $pc2mapd2[($d >> 16) & 0xFF] |
1319
+ $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF];
1320
+
1321
+ // Reorder: odd bytes/even bytes. Push the result in key schedule.
1322
+ $val1 = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) |
1323
+ (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF);
1324
+ $val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) |
1325
+ (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF);
1326
+ $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val1;
1327
+ $keys[$des_round][CRYPT_DES_DECRYPT][$ki - 1] = $val1;
1328
+ $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val2;
1329
+ $keys[$des_round][CRYPT_DES_DECRYPT][$ki ] = $val2;
1330
+ }
1331
+ }
1332
+
1333
+ switch ($this->des_rounds) {
1334
+ case 3: // 3DES keys
1335
+ $this->keys = array(
1336
+ CRYPT_DES_ENCRYPT => array_merge(
1337
+ $keys[0][CRYPT_DES_ENCRYPT],
1338
+ $keys[1][CRYPT_DES_DECRYPT],
1339
+ $keys[2][CRYPT_DES_ENCRYPT]
1340
+ ),
1341
+ CRYPT_DES_DECRYPT => array_merge(
1342
+ $keys[2][CRYPT_DES_DECRYPT],
1343
+ $keys[1][CRYPT_DES_ENCRYPT],
1344
+ $keys[0][CRYPT_DES_DECRYPT]
1345
+ )
1346
+ );
1347
+ break;
1348
+ // case 1: // DES keys
1349
+ default:
1350
+ $this->keys = array(
1351
+ CRYPT_DES_ENCRYPT => $keys[0][CRYPT_DES_ENCRYPT],
1352
+ CRYPT_DES_DECRYPT => $keys[0][CRYPT_DES_DECRYPT]
1353
+ );
1354
+ }
1355
+ }
1356
+
1357
+ /**
1358
+ * Setup the performance-optimized function for de/encrypt()
1359
+ *
1360
+ * @see Crypt_Base::_setupInlineCrypt()
1361
+ * @access private
1362
+ */
1363
+ function _setupInlineCrypt()
1364
+ {
1365
+ $lambda_functions =& Crypt_DES::_getLambdaFunctions();
1366
+
1367
+ // Engine configuration for:
1368
+ // - DES ($des_rounds == 1) or
1369
+ // - 3DES ($des_rounds == 3)
1370
+ $des_rounds = $this->des_rounds;
1371
+
1372
+ // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
1373
+ // (Currently, for Crypt_DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
1374
+ // (Currently, for Crypt_TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
1375
+ // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
1376
+ $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
1377
+
1378
+ // Generation of a unique hash for our generated code
1379
+ $code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
1380
+ if ($gen_hi_opt_code) {
1381
+ // For hi-optimized code, we create for each combination of
1382
+ // $mode, $des_rounds and $this->key its own encrypt/decrypt function.
1383
+ // After max 10 hi-optimized functions, we create generic
1384
+ // (still very fast.. but not ultra) functions for each $mode/$des_rounds
1385
+ // Currently 2 * 5 generic functions will be then max. possible.
1386
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
1387
+ }
1388
+
1389
+ // Is there a re-usable $lambda_functions in there? If not, we have to create it.
1390
+ if (!isset($lambda_functions[$code_hash])) {
1391
+ // Init code for both, encrypt and decrypt.
1392
+ $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
1393
+ if (!$sbox1) {
1394
+ $sbox1 = array_map("intval", $self->sbox1);
1395
+ $sbox2 = array_map("intval", $self->sbox2);
1396
+ $sbox3 = array_map("intval", $self->sbox3);
1397
+ $sbox4 = array_map("intval", $self->sbox4);
1398
+ $sbox5 = array_map("intval", $self->sbox5);
1399
+ $sbox6 = array_map("intval", $self->sbox6);
1400
+ $sbox7 = array_map("intval", $self->sbox7);
1401
+ $sbox8 = array_map("intval", $self->sbox8);'
1402
+ /* Merge $shuffle with $[inv]ipmap */ . '
1403
+ for ($i = 0; $i < 256; ++$i) {
1404
+ $shuffleip[] = $self->shuffle[$self->ipmap[$i]];
1405
+ $shuffleinvip[] = $self->shuffle[$self->invipmap[$i]];
1406
+ }
1407
+ }
1408
+ ';
1409
+
1410
+ switch (true) {
1411
+ case $gen_hi_opt_code:
1412
+ // In Hi-optimized code mode, we use our [3]DES key schedule as hardcoded integers.
1413
+ // No futher initialisation of the $keys schedule is necessary.
1414
+ // That is the extra performance boost.
1415
+ $k = array(
1416
+ CRYPT_DES_ENCRYPT => $this->keys[CRYPT_DES_ENCRYPT],
1417
+ CRYPT_DES_DECRYPT => $this->keys[CRYPT_DES_DECRYPT]
1418
+ );
1419
+ $init_encrypt = '';
1420
+ $init_decrypt = '';
1421
+ break;
1422
+ default:
1423
+ // In generic optimized code mode, we have to use, as the best compromise [currently],
1424
+ // our key schedule as $ke/$kd arrays. (with hardcoded indexes...)
1425
+ $k = array(
1426
+ CRYPT_DES_ENCRYPT => array(),
1427
+ CRYPT_DES_DECRYPT => array()
1428
+ );
1429
+ for ($i = 0, $c = count($this->keys[CRYPT_DES_ENCRYPT]); $i < $c; ++$i) {
1430
+ $k[CRYPT_DES_ENCRYPT][$i] = '$ke[' . $i . ']';
1431
+ $k[CRYPT_DES_DECRYPT][$i] = '$kd[' . $i . ']';
1432
+ }
1433
+ $init_encrypt = '$ke = $self->keys[CRYPT_DES_ENCRYPT];';
1434
+ $init_decrypt = '$kd = $self->keys[CRYPT_DES_DECRYPT];';
1435
+ break;
1436
+ }
1437
+
1438
+ // Creating code for en- and decryption.
1439
+ $crypt_block = array();
1440
+ foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) {
1441
+ /* Do the initial IP permutation. */
1442
+ $crypt_block[$c] = '
1443
+ $in = unpack("N*", $in);
1444
+ $l = $in[1];
1445
+ $r = $in[2];
1446
+ $in = unpack("N*",
1447
+ ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
1448
+ ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
1449
+ ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
1450
+ ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
1451
+ ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
1452
+ ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
1453
+ ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
1454
+ ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01")
1455
+ );
1456
+ ' . /* Extract L0 and R0 */ '
1457
+ $l = $in[1];
1458
+ $r = $in[2];
1459
+ ';
1460
+
1461
+ $l = '$l';
1462
+ $r = '$r';
1463
+
1464
+ // Perform DES or 3DES.
1465
+ for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) {
1466
+ // Perform the 16 steps.
1467
+ for ($i = 0; $i < 16; ++$i) {
1468
+ // start of "the Feistel (F) function" - see the following URL:
1469
+ // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
1470
+ // Merge key schedule.
1471
+ $crypt_block[$c].= '
1472
+ $b1 = ((' . $r . ' >> 3) & 0x1FFFFFFF) ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
1473
+ $b2 = ((' . $r . ' >> 31) & 0x00000001) ^ (' . $r . ' << 1) ^ ' . $k[$c][++$ki] . ';' .
1474
+ /* S-box indexing. */
1475
+ $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
1476
+ $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
1477
+ $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^
1478
+ $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ ' . $l . ';
1479
+ ';
1480
+ // end of "the Feistel (F) function"
1481
+
1482
+ // swap L & R
1483
+ list($l, $r) = array($r, $l);
1484
+ }
1485
+ list($l, $r) = array($r, $l);
1486
+ }
1487
+
1488
+ // Perform the inverse IP permutation.
1489
+ $crypt_block[$c].= '$in =
1490
+ ($shuffleinvip[($l >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
1491
+ ($shuffleinvip[($r >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
1492
+ ($shuffleinvip[($l >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
1493
+ ($shuffleinvip[($r >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
1494
+ ($shuffleinvip[($l >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
1495
+ ($shuffleinvip[($r >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
1496
+ ($shuffleinvip[ $l & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
1497
+ ($shuffleinvip[ $r & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
1498
+ ';
1499
+ }
1500
+
1501
+ // Creates the inline-crypt function
1502
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
1503
+ array(
1504
+ 'init_crypt' => $init_crypt,
1505
+ 'init_encrypt' => $init_encrypt,
1506
+ 'init_decrypt' => $init_decrypt,
1507
+ 'encrypt_block' => $crypt_block[CRYPT_DES_ENCRYPT],
1508
+ 'decrypt_block' => $crypt_block[CRYPT_DES_DECRYPT]
1509
+ )
1510
+ );
1511
+ }
1512
+
1513
+ // Set the inline-crypt function as callback in: $this->inline_crypt
1514
+ $this->inline_crypt = $lambda_functions[$code_hash];
1515
+ }
1516
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php ADDED
@@ -0,0 +1,861 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
5
+ *
6
+ * Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
7
+ *
8
+ * md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
9
+ *
10
+ * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to
11
+ * the hash. If no valid algorithm is provided, sha1 will be used.
12
+ *
13
+ * PHP versions 4 and 5
14
+ *
15
+ * {@internal The variable names are the same as those in
16
+ * {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
17
+ *
18
+ * Here's a short example of how to use this library:
19
+ * <code>
20
+ * <?php
21
+ * include 'Crypt/Hash.php';
22
+ *
23
+ * $hash = new Crypt_Hash('sha1');
24
+ *
25
+ * $hash->setKey('abcdefg');
26
+ *
27
+ * echo base64_encode($hash->hash('abcdefg'));
28
+ * ?>
29
+ * </code>
30
+ *
31
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
48
+ *
49
+ * @category Crypt
50
+ * @package Crypt_Hash
51
+ * @author Jim Wigginton <terrafrost@php.net>
52
+ * @copyright 2007 Jim Wigginton
53
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
54
+ * @link http://phpseclib.sourceforge.net
55
+ */
56
+
57
+ /**#@+
58
+ * @access private
59
+ * @see self::Crypt_Hash()
60
+ */
61
+ /**
62
+ * Toggles the internal implementation
63
+ */
64
+ define('CRYPT_HASH_MODE_INTERNAL', 1);
65
+ /**
66
+ * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
67
+ */
68
+ define('CRYPT_HASH_MODE_MHASH', 2);
69
+ /**
70
+ * Toggles the hash() implementation, which works on PHP 5.1.2+.
71
+ */
72
+ define('CRYPT_HASH_MODE_HASH', 3);
73
+ /**#@-*/
74
+
75
+ /**
76
+ * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
77
+ *
78
+ * @package Crypt_Hash
79
+ * @author Jim Wigginton <terrafrost@php.net>
80
+ * @access public
81
+ */
82
+ class Crypt_Hash
83
+ {
84
+ /**
85
+ * Hash Parameter
86
+ *
87
+ * @see self::setHash()
88
+ * @var int
89
+ * @access private
90
+ */
91
+ var $hashParam;
92
+
93
+ /**
94
+ * Byte-length of compression blocks / key (Internal HMAC)
95
+ *
96
+ * @see self::setAlgorithm()
97
+ * @var int
98
+ * @access private
99
+ */
100
+ var $b;
101
+
102
+ /**
103
+ * Byte-length of hash output (Internal HMAC)
104
+ *
105
+ * @see self::setHash()
106
+ * @var int
107
+ * @access private
108
+ */
109
+ var $l = false;
110
+
111
+ /**
112
+ * Hash Algorithm
113
+ *
114
+ * @see self::setHash()
115
+ * @var string
116
+ * @access private
117
+ */
118
+ var $hash;
119
+
120
+ /**
121
+ * Key
122
+ *
123
+ * @see self::setKey()
124
+ * @var string
125
+ * @access private
126
+ */
127
+ var $key = false;
128
+
129
+ /**
130
+ * Outer XOR (Internal HMAC)
131
+ *
132
+ * @see self::setKey()
133
+ * @var string
134
+ * @access private
135
+ */
136
+ var $opad;
137
+
138
+ /**
139
+ * Inner XOR (Internal HMAC)
140
+ *
141
+ * @see self::setKey()
142
+ * @var string
143
+ * @access private
144
+ */
145
+ var $ipad;
146
+
147
+ /**
148
+ * Default Constructor.
149
+ *
150
+ * @param string $hash
151
+ * @return Crypt_Hash
152
+ * @access public
153
+ */
154
+ function __construct($hash = 'sha1')
155
+ {
156
+ if (!defined('CRYPT_HASH_MODE')) {
157
+ switch (true) {
158
+ case extension_loaded('hash'):
159
+ define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
160
+ break;
161
+ case extension_loaded('mhash'):
162
+ define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
163
+ break;
164
+ default:
165
+ define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
166
+ }
167
+ }
168
+
169
+ $this->setHash($hash);
170
+ }
171
+
172
+ /**
173
+ * PHP4 compatible Default Constructor.
174
+ *
175
+ * @see self::__construct()
176
+ * @param int $mode
177
+ * @access public
178
+ */
179
+ function Crypt_Hash($hash = 'sha1')
180
+ {
181
+ $this->__construct($hash);
182
+ }
183
+
184
+ /**
185
+ * Sets the key for HMACs
186
+ *
187
+ * Keys can be of any length.
188
+ *
189
+ * @access public
190
+ * @param string $key
191
+ */
192
+ function setKey($key = false)
193
+ {
194
+ $this->key = $key;
195
+ }
196
+
197
+ /**
198
+ * Gets the hash function.
199
+ *
200
+ * As set by the constructor or by the setHash() method.
201
+ *
202
+ * @access public
203
+ * @return string
204
+ */
205
+ function getHash()
206
+ {
207
+ return $this->hashParam;
208
+ }
209
+
210
+ /**
211
+ * Sets the hash function.
212
+ *
213
+ * @access public
214
+ * @param string $hash
215
+ */
216
+ function setHash($hash)
217
+ {
218
+ $this->hashParam = $hash = strtolower($hash);
219
+ switch ($hash) {
220
+ case 'md5-96':
221
+ case 'sha1-96':
222
+ case 'sha256-96':
223
+ case 'sha512-96':
224
+ $hash = substr($hash, 0, -3);
225
+ $this->l = 12; // 96 / 8 = 12
226
+ break;
227
+ case 'md2':
228
+ case 'md5':
229
+ $this->l = 16;
230
+ break;
231
+ case 'sha1':
232
+ $this->l = 20;
233
+ break;
234
+ case 'sha256':
235
+ $this->l = 32;
236
+ break;
237
+ case 'sha384':
238
+ $this->l = 48;
239
+ break;
240
+ case 'sha512':
241
+ $this->l = 64;
242
+ }
243
+
244
+ switch ($hash) {
245
+ case 'md2':
246
+ $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ?
247
+ CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL;
248
+ break;
249
+ case 'sha384':
250
+ case 'sha512':
251
+ $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
252
+ break;
253
+ default:
254
+ $mode = CRYPT_HASH_MODE;
255
+ }
256
+
257
+ switch ($mode) {
258
+ case CRYPT_HASH_MODE_MHASH:
259
+ switch ($hash) {
260
+ case 'md5':
261
+ $this->hash = MHASH_MD5;
262
+ break;
263
+ case 'sha256':
264
+ $this->hash = MHASH_SHA256;
265
+ break;
266
+ case 'sha1':
267
+ default:
268
+ $this->hash = MHASH_SHA1;
269
+ }
270
+ return;
271
+ case CRYPT_HASH_MODE_HASH:
272
+ switch ($hash) {
273
+ case 'md5':
274
+ $this->hash = 'md5';
275
+ return;
276
+ case 'md2':
277
+ case 'sha256':
278
+ case 'sha384':
279
+ case 'sha512':
280
+ $this->hash = $hash;
281
+ return;
282
+ case 'sha1':
283
+ default:
284
+ $this->hash = 'sha1';
285
+ }
286
+ return;
287
+ }
288
+
289
+ switch ($hash) {
290
+ case 'md2':
291
+ $this->b = 16;
292
+ $this->hash = array($this, '_md2');
293
+ break;
294
+ case 'md5':
295
+ $this->b = 64;
296
+ $this->hash = array($this, '_md5');
297
+ break;
298
+ case 'sha256':
299
+ $this->b = 64;
300
+ $this->hash = array($this, '_sha256');
301
+ break;
302
+ case 'sha384':
303
+ case 'sha512':
304
+ $this->b = 128;
305
+ $this->hash = array($this, '_sha512');
306
+ break;
307
+ case 'sha1':
308
+ default:
309
+ $this->b = 64;
310
+ $this->hash = array($this, '_sha1');
311
+ }
312
+
313
+ $this->ipad = str_repeat(chr(0x36), $this->b);
314
+ $this->opad = str_repeat(chr(0x5C), $this->b);
315
+ }
316
+
317
+ /**
318
+ * Compute the HMAC.
319
+ *
320
+ * @access public
321
+ * @param string $text
322
+ * @return string
323
+ */
324
+ function hash($text)
325
+ {
326
+ $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
327
+
328
+ if (!empty($this->key) || is_string($this->key)) {
329
+ switch ($mode) {
330
+ case CRYPT_HASH_MODE_MHASH:
331
+ $output = mhash($this->hash, $text, $this->key);
332
+ break;
333
+ case CRYPT_HASH_MODE_HASH:
334
+ $output = hash_hmac($this->hash, $text, $this->key, true);
335
+ break;
336
+ case CRYPT_HASH_MODE_INTERNAL:
337
+ /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
338
+ resultant L byte string as the actual key to HMAC."
339
+
340
+ -- http://tools.ietf.org/html/rfc2104#section-2 */
341
+ $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
342
+
343
+ $key = str_pad($key, $this->b, chr(0)); // step 1
344
+ $temp = $this->ipad ^ $key; // step 2
345
+ $temp .= $text; // step 3
346
+ $temp = call_user_func($this->hash, $temp); // step 4
347
+ $output = $this->opad ^ $key; // step 5
348
+ $output.= $temp; // step 6
349
+ $output = call_user_func($this->hash, $output); // step 7
350
+ }
351
+ } else {
352
+ switch ($mode) {
353
+ case CRYPT_HASH_MODE_MHASH:
354
+ $output = mhash($this->hash, $text);
355
+ break;
356
+ case CRYPT_HASH_MODE_HASH:
357
+ $output = hash($this->hash, $text, true);
358
+ break;
359
+ case CRYPT_HASH_MODE_INTERNAL:
360
+ $output = call_user_func($this->hash, $text);
361
+ }
362
+ }
363
+
364
+ return substr($output, 0, $this->l);
365
+ }
366
+
367
+ /**
368
+ * Returns the hash length (in bytes)
369
+ *
370
+ * @access public
371
+ * @return int
372
+ */
373
+ function getLength()
374
+ {
375
+ return $this->l;
376
+ }
377
+
378
+ /**
379
+ * Wrapper for MD5
380
+ *
381
+ * @access private
382
+ * @param string $m
383
+ */
384
+ function _md5($m)
385
+ {
386
+ return pack('H*', md5($m));
387
+ }
388
+
389
+ /**
390
+ * Wrapper for SHA1
391
+ *
392
+ * @access private
393
+ * @param string $m
394
+ */
395
+ function _sha1($m)
396
+ {
397
+ return pack('H*', sha1($m));
398
+ }
399
+
400
+ /**
401
+ * Pure-PHP implementation of MD2
402
+ *
403
+ * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
404
+ *
405
+ * @access private
406
+ * @param string $m
407
+ */
408
+ function _md2($m)
409
+ {
410
+ static $s = array(
411
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
412
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
413
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
414
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
415
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
416
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
417
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
418
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
419
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
420
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
421
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
422
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
423
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
424
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
425
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
426
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
427
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
428
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
429
+ );
430
+
431
+ // Step 1. Append Padding Bytes
432
+ $pad = 16 - (strlen($m) & 0xF);
433
+ $m.= str_repeat(chr($pad), $pad);
434
+
435
+ $length = strlen($m);
436
+
437
+ // Step 2. Append Checksum
438
+ $c = str_repeat(chr(0), 16);
439
+ $l = chr(0);
440
+ for ($i = 0; $i < $length; $i+= 16) {
441
+ for ($j = 0; $j < 16; $j++) {
442
+ // RFC1319 incorrectly states that C[j] should be set to S[c xor L]
443
+ //$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
444
+ // per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
445
+ $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
446
+ $l = $c[$j];
447
+ }
448
+ }
449
+ $m.= $c;
450
+
451
+ $length+= 16;
452
+
453
+ // Step 3. Initialize MD Buffer
454
+ $x = str_repeat(chr(0), 48);
455
+
456
+ // Step 4. Process Message in 16-Byte Blocks
457
+ for ($i = 0; $i < $length; $i+= 16) {
458
+ for ($j = 0; $j < 16; $j++) {
459
+ $x[$j + 16] = $m[$i + $j];
460
+ $x[$j + 32] = $x[$j + 16] ^ $x[$j];
461
+ }
462
+ $t = chr(0);
463
+ for ($j = 0; $j < 18; $j++) {
464
+ for ($k = 0; $k < 48; $k++) {
465
+ $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
466
+ //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
467
+ }
468
+ $t = chr(ord($t) + $j);
469
+ }
470
+ }
471
+
472
+ // Step 5. Output
473
+ return substr($x, 0, 16);
474
+ }
475
+
476
+ /**
477
+ * Pure-PHP implementation of SHA256
478
+ *
479
+ * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
480
+ *
481
+ * @access private
482
+ * @param string $m
483
+ */
484
+ function _sha256($m)
485
+ {
486
+ if (extension_loaded('suhosin')) {
487
+ return pack('H*', sha256($m));
488
+ }
489
+
490
+ // Initialize variables
491
+ $hash = array(
492
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
493
+ );
494
+ // Initialize table of round constants
495
+ // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
496
+ static $k = array(
497
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
498
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
499
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
500
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
501
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
502
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
503
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
504
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
505
+ );
506
+
507
+ // Pre-processing
508
+ $length = strlen($m);
509
+ // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
510
+ $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
511
+ $m[$length] = chr(0x80);
512
+ // we don't support hashing strings 512MB long
513
+ $m.= pack('N2', 0, $length << 3);
514
+
515
+ // Process the message in successive 512-bit chunks
516
+ $chunks = str_split($m, 64);
517
+ foreach ($chunks as $chunk) {
518
+ $w = array();
519
+ for ($i = 0; $i < 16; $i++) {
520
+ extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
521
+ $w[] = $temp;
522
+ }
523
+
524
+ // Extend the sixteen 32-bit words into sixty-four 32-bit words
525
+ for ($i = 16; $i < 64; $i++) {
526
+ // @codingStandardsIgnoreStart
527
+ $s0 = $this->_rightRotate($w[$i - 15], 7) ^
528
+ $this->_rightRotate($w[$i - 15], 18) ^
529
+ $this->_rightShift( $w[$i - 15], 3);
530
+ $s1 = $this->_rightRotate($w[$i - 2], 17) ^
531
+ $this->_rightRotate($w[$i - 2], 19) ^
532
+ $this->_rightShift( $w[$i - 2], 10);
533
+ // @codingStandardsIgnoreEnd
534
+ $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
535
+ }
536
+
537
+ // Initialize hash value for this chunk
538
+ list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
539
+
540
+ // Main loop
541
+ for ($i = 0; $i < 64; $i++) {
542
+ $s0 = $this->_rightRotate($a, 2) ^
543
+ $this->_rightRotate($a, 13) ^
544
+ $this->_rightRotate($a, 22);
545
+ $maj = ($a & $b) ^
546
+ ($a & $c) ^
547
+ ($b & $c);
548
+ $t2 = $this->_add($s0, $maj);
549
+
550
+ $s1 = $this->_rightRotate($e, 6) ^
551
+ $this->_rightRotate($e, 11) ^
552
+ $this->_rightRotate($e, 25);
553
+ $ch = ($e & $f) ^
554
+ ($this->_not($e) & $g);
555
+ $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
556
+
557
+ $h = $g;
558
+ $g = $f;
559
+ $f = $e;
560
+ $e = $this->_add($d, $t1);
561
+ $d = $c;
562
+ $c = $b;
563
+ $b = $a;
564
+ $a = $this->_add($t1, $t2);
565
+ }
566
+
567
+ // Add this chunk's hash to result so far
568
+ $hash = array(
569
+ $this->_add($hash[0], $a),
570
+ $this->_add($hash[1], $b),
571
+ $this->_add($hash[2], $c),
572
+ $this->_add($hash[3], $d),
573
+ $this->_add($hash[4], $e),
574
+ $this->_add($hash[5], $f),
575
+ $this->_add($hash[6], $g),
576
+ $this->_add($hash[7], $h)
577
+ );
578
+ }
579
+
580
+ // Produce the final hash value (big-endian)
581
+ return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
582
+ }
583
+
584
+ /**
585
+ * Pure-PHP implementation of SHA384 and SHA512
586
+ *
587
+ * @access private
588
+ * @param string $m
589
+ */
590
+ function _sha512($m)
591
+ {
592
+ if (!class_exists('Math_BigInteger')) {
593
+ include_once 'Math/BigInteger.php';
594
+ }
595
+
596
+ static $init384, $init512, $k;
597
+
598
+ if (!isset($k)) {
599
+ // Initialize variables
600
+ $init384 = array( // initial values for SHA384
601
+ 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
602
+ '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
603
+ );
604
+ $init512 = array( // initial values for SHA512
605
+ '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
606
+ '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
607
+ );
608
+
609
+ for ($i = 0; $i < 8; $i++) {
610
+ $init384[$i] = new Math_BigInteger($init384[$i], 16);
611
+ $init384[$i]->setPrecision(64);
612
+ $init512[$i] = new Math_BigInteger($init512[$i], 16);
613
+ $init512[$i]->setPrecision(64);
614
+ }
615
+
616
+ // Initialize table of round constants
617
+ // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
618
+ $k = array(
619
+ '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
620
+ '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
621
+ 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
622
+ '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
623
+ 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
624
+ '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
625
+ '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
626
+ 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
627
+ '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
628
+ '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
629
+ 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
630
+ 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
631
+ '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
632
+ '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
633
+ '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
634
+ '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
635
+ 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
636
+ '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
637
+ '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
638
+ '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
639
+ );
640
+
641
+ for ($i = 0; $i < 80; $i++) {
642
+ $k[$i] = new Math_BigInteger($k[$i], 16);
643
+ }
644
+ }
645
+
646
+ $hash = $this->l == 48 ? $init384 : $init512;
647
+
648
+ // Pre-processing
649
+ $length = strlen($m);
650
+ // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
651
+ $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
652
+ $m[$length] = chr(0x80);
653
+ // we don't support hashing strings 512MB long
654
+ $m.= pack('N4', 0, 0, 0, $length << 3);
655
+
656
+ // Process the message in successive 1024-bit chunks
657
+ $chunks = str_split($m, 128);
658
+ foreach ($chunks as $chunk) {
659
+ $w = array();
660
+ for ($i = 0; $i < 16; $i++) {
661
+ $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
662
+ $temp->setPrecision(64);
663
+ $w[] = $temp;
664
+ }
665
+
666
+ // Extend the sixteen 32-bit words into eighty 32-bit words
667
+ for ($i = 16; $i < 80; $i++) {
668
+ $temp = array(
669
+ $w[$i - 15]->bitwise_rightRotate(1),
670
+ $w[$i - 15]->bitwise_rightRotate(8),
671
+ $w[$i - 15]->bitwise_rightShift(7)
672
+ );
673
+ $s0 = $temp[0]->bitwise_xor($temp[1]);
674
+ $s0 = $s0->bitwise_xor($temp[2]);
675
+ $temp = array(
676
+ $w[$i - 2]->bitwise_rightRotate(19),
677
+ $w[$i - 2]->bitwise_rightRotate(61),
678
+ $w[$i - 2]->bitwise_rightShift(6)
679
+ );
680
+ $s1 = $temp[0]->bitwise_xor($temp[1]);
681
+ $s1 = $s1->bitwise_xor($temp[2]);
682
+ $w[$i] = $w[$i - 16]->copy();
683
+ $w[$i] = $w[$i]->add($s0);
684
+ $w[$i] = $w[$i]->add($w[$i - 7]);
685
+ $w[$i] = $w[$i]->add($s1);
686
+ }
687
+
688
+ // Initialize hash value for this chunk
689
+ $a = $hash[0]->copy();
690
+ $b = $hash[1]->copy();
691
+ $c = $hash[2]->copy();
692
+ $d = $hash[3]->copy();
693
+ $e = $hash[4]->copy();
694
+ $f = $hash[5]->copy();
695
+ $g = $hash[6]->copy();
696
+ $h = $hash[7]->copy();
697
+
698
+ // Main loop
699
+ for ($i = 0; $i < 80; $i++) {
700
+ $temp = array(
701
+ $a->bitwise_rightRotate(28),
702
+ $a->bitwise_rightRotate(34),
703
+ $a->bitwise_rightRotate(39)
704
+ );
705
+ $s0 = $temp[0]->bitwise_xor($temp[1]);
706
+ $s0 = $s0->bitwise_xor($temp[2]);
707
+ $temp = array(
708
+ $a->bitwise_and($b),
709
+ $a->bitwise_and($c),
710
+ $b->bitwise_and($c)
711
+ );
712
+ $maj = $temp[0]->bitwise_xor($temp[1]);
713
+ $maj = $maj->bitwise_xor($temp[2]);
714
+ $t2 = $s0->add($maj);
715
+
716
+ $temp = array(
717
+ $e->bitwise_rightRotate(14),
718
+ $e->bitwise_rightRotate(18),
719
+ $e->bitwise_rightRotate(41)
720
+ );
721
+ $s1 = $temp[0]->bitwise_xor($temp[1]);
722
+ $s1 = $s1->bitwise_xor($temp[2]);
723
+ $temp = array(
724
+ $e->bitwise_and($f),
725
+ $g->bitwise_and($e->bitwise_not())
726
+ );
727
+ $ch = $temp[0]->bitwise_xor($temp[1]);
728
+ $t1 = $h->add($s1);
729
+ $t1 = $t1->add($ch);
730
+ $t1 = $t1->add($k[$i]);
731
+ $t1 = $t1->add($w[$i]);
732
+
733
+ $h = $g->copy();
734
+ $g = $f->copy();
735
+ $f = $e->copy();
736
+ $e = $d->add($t1);
737
+ $d = $c->copy();
738
+ $c = $b->copy();
739
+ $b = $a->copy();
740
+ $a = $t1->add($t2);
741
+ }
742
+
743
+ // Add this chunk's hash to result so far
744
+ $hash = array(
745
+ $hash[0]->add($a),
746
+ $hash[1]->add($b),
747
+ $hash[2]->add($c),
748
+ $hash[3]->add($d),
749
+ $hash[4]->add($e),
750
+ $hash[5]->add($f),
751
+ $hash[6]->add($g),
752
+ $hash[7]->add($h)
753
+ );
754
+ }
755
+
756
+ // Produce the final hash value (big-endian)
757
+ // (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
758
+ $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
759
+ $hash[4]->toBytes() . $hash[5]->toBytes();
760
+ if ($this->l != 48) {
761
+ $temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
762
+ }
763
+
764
+ return $temp;
765
+ }
766
+
767
+ /**
768
+ * Right Rotate
769
+ *
770
+ * @access private
771
+ * @param int $int
772
+ * @param int $amt
773
+ * @see self::_sha256()
774
+ * @return int
775
+ */
776
+ function _rightRotate($int, $amt)
777
+ {
778
+ $invamt = 32 - $amt;
779
+ $mask = (1 << $invamt) - 1;
780
+ return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
781
+ }
782
+
783
+ /**
784
+ * Right Shift
785
+ *
786
+ * @access private
787
+ * @param int $int
788
+ * @param int $amt
789
+ * @see self::_sha256()
790
+ * @return int
791
+ */
792
+ function _rightShift($int, $amt)
793
+ {
794
+ $mask = (1 << (32 - $amt)) - 1;
795
+ return ($int >> $amt) & $mask;
796
+ }
797
+
798
+ /**
799
+ * Not
800
+ *
801
+ * @access private
802
+ * @param int $int
803
+ * @see self::_sha256()
804
+ * @return int
805
+ */
806
+ function _not($int)
807
+ {
808
+ return ~$int & 0xFFFFFFFF;
809
+ }
810
+
811
+ /**
812
+ * Add
813
+ *
814
+ * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
815
+ * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
816
+ *
817
+ * @param int $...
818
+ * @return int
819
+ * @see self::_sha256()
820
+ * @access private
821
+ */
822
+ function _add()
823
+ {
824
+ static $mod;
825
+ if (!isset($mod)) {
826
+ $mod = pow(2, 32);
827
+ }
828
+
829
+ $result = 0;
830
+ $arguments = func_get_args();
831
+ foreach ($arguments as $argument) {
832
+ $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
833
+ }
834
+
835
+ // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
836
+ // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
837
+ if (is_int($result) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
838
+ return fmod($result, $mod);
839
+ }
840
+
841
+ return (fmod($result, 0x80000000) & 0x7FFFFFFF) |
842
+ ((fmod(floor($result / 0x80000000), 2) & 1) << 31);
843
+ }
844
+
845
+ /**
846
+ * String Shift
847
+ *
848
+ * Inspired by array_shift
849
+ *
850
+ * @param string $string
851
+ * @param int $index
852
+ * @return string
853
+ * @access private
854
+ */
855
+ function _string_shift(&$string, $index = 1)
856
+ {
857
+ $substr = substr($string, 0, $index);
858
+ $string = substr($string, $index);
859
+ return $substr;
860
+ }
861
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php ADDED
@@ -0,0 +1,761 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of RC2.
5
+ *
6
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * Useful resources are as follows:
11
+ *
12
+ * - {@link http://tools.ietf.org/html/rfc2268}
13
+ *
14
+ * Here's a short example of how to use this library:
15
+ * <code>
16
+ * <?php
17
+ * include 'Crypt/RC2.php';
18
+ *
19
+ * $rc2 = new Crypt_RC2();
20
+ *
21
+ * $rc2->setKey('abcdefgh');
22
+ *
23
+ * $plaintext = str_repeat('a', 1024);
24
+ *
25
+ * echo $rc2->decrypt($rc2->encrypt($plaintext));
26
+ * ?>
27
+ * </code>
28
+ *
29
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * of this software and associated documentation files (the "Software"), to deal
31
+ * in the Software without restriction, including without limitation the rights
32
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ * copies of the Software, and to permit persons to whom the Software is
34
+ * furnished to do so, subject to the following conditions:
35
+ *
36
+ * The above copyright notice and this permission notice shall be included in
37
+ * all copies or substantial portions of the Software.
38
+ *
39
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * THE SOFTWARE.
46
+ *
47
+ * @category Crypt
48
+ * @package Crypt_RC2
49
+ * @author Patrick Monnerat <pm@datasphere.ch>
50
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
51
+ * @link http://phpseclib.sourceforge.net
52
+ */
53
+
54
+ /**
55
+ * Include Crypt_Base
56
+ *
57
+ * Base cipher class
58
+ */
59
+ if (!class_exists('Crypt_Base')) {
60
+ include_once 'Base.php';
61
+ }
62
+
63
+ /**#@+
64
+ * @access public
65
+ * @see self::encrypt()
66
+ * @see self::decrypt()
67
+ */
68
+ /**
69
+ * Encrypt / decrypt using the Counter mode.
70
+ *
71
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
72
+ *
73
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
74
+ */
75
+ define('CRYPT_RC2_MODE_CTR', CRYPT_MODE_CTR);
76
+ /**
77
+ * Encrypt / decrypt using the Electronic Code Book mode.
78
+ *
79
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
80
+ */
81
+ define('CRYPT_RC2_MODE_ECB', CRYPT_MODE_ECB);
82
+ /**
83
+ * Encrypt / decrypt using the Code Book Chaining mode.
84
+ *
85
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
86
+ */
87
+ define('CRYPT_RC2_MODE_CBC', CRYPT_MODE_CBC);
88
+ /**
89
+ * Encrypt / decrypt using the Cipher Feedback mode.
90
+ *
91
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
92
+ */
93
+ define('CRYPT_RC2_MODE_CFB', CRYPT_MODE_CFB);
94
+ /**
95
+ * Encrypt / decrypt using the Cipher Feedback mode.
96
+ *
97
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
98
+ */
99
+ define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB);
100
+ /**#@-*/
101
+
102
+ /**
103
+ * Pure-PHP implementation of RC2.
104
+ *
105
+ * @package Crypt_RC2
106
+ * @access public
107
+ */
108
+ class Crypt_RC2 extends Crypt_Base
109
+ {
110
+ /**
111
+ * Block Length of the cipher
112
+ *
113
+ * @see Crypt_Base::block_size
114
+ * @var int
115
+ * @access private
116
+ */
117
+ var $block_size = 8;
118
+
119
+ /**
120
+ * The Key
121
+ *
122
+ * @see Crypt_Base::key
123
+ * @see self::setKey()
124
+ * @var string
125
+ * @access private
126
+ */
127
+ var $key;
128
+
129
+ /**
130
+ * The Original (unpadded) Key
131
+ *
132
+ * @see Crypt_Base::key
133
+ * @see self::setKey()
134
+ * @see self::encrypt()
135
+ * @see self::decrypt()
136
+ * @var string
137
+ * @access private
138
+ */
139
+ var $orig_key;
140
+
141
+ /**
142
+ * Don't truncate / null pad key
143
+ *
144
+ * @see Crypt_Base::_clearBuffers()
145
+ * @var bool
146
+ * @access private
147
+ */
148
+ var $skip_key_adjustment = true;
149
+
150
+ /**
151
+ * Key Length (in bytes)
152
+ *
153
+ * @see Crypt_RC2::setKeyLength()
154
+ * @var int
155
+ * @access private
156
+ */
157
+ var $key_length = 16; // = 128 bits
158
+
159
+ /**
160
+ * The namespace used by the cipher for its constants.
161
+ *
162
+ * @see Crypt_Base::const_namespace
163
+ * @var string
164
+ * @access private
165
+ */
166
+ var $const_namespace = 'RC2';
167
+
168
+ /**
169
+ * The mcrypt specific name of the cipher
170
+ *
171
+ * @see Crypt_Base::cipher_name_mcrypt
172
+ * @var string
173
+ * @access private
174
+ */
175
+ var $cipher_name_mcrypt = 'rc2';
176
+
177
+ /**
178
+ * Optimizing value while CFB-encrypting
179
+ *
180
+ * @see Crypt_Base::cfb_init_len
181
+ * @var int
182
+ * @access private
183
+ */
184
+ var $cfb_init_len = 500;
185
+
186
+ /**
187
+ * The key length in bits.
188
+ *
189
+ * @see self::setKeyLength()
190
+ * @see self::setKey()
191
+ * @var int
192
+ * @access private
193
+ * @internal Should be in range [1..1024].
194
+ * @internal Changing this value after setting the key has no effect.
195
+ */
196
+ var $default_key_length = 1024;
197
+
198
+ /**
199
+ * The key length in bits.
200
+ *
201
+ * @see self::isValidEnine()
202
+ * @see self::setKey()
203
+ * @var int
204
+ * @access private
205
+ * @internal Should be in range [1..1024].
206
+ */
207
+ var $current_key_length;
208
+
209
+ /**
210
+ * The Key Schedule
211
+ *
212
+ * @see self::_setupKey()
213
+ * @var array
214
+ * @access private
215
+ */
216
+ var $keys;
217
+
218
+ /**
219
+ * Key expansion randomization table.
220
+ * Twice the same 256-value sequence to save a modulus in key expansion.
221
+ *
222
+ * @see self::setKey()
223
+ * @var array
224
+ * @access private
225
+ */
226
+ var $pitable = array(
227
+ 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
228
+ 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
229
+ 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
230
+ 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
231
+ 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
232
+ 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
233
+ 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
234
+ 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
235
+ 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
236
+ 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
237
+ 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
238
+ 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
239
+ 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
240
+ 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
241
+ 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
242
+ 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
243
+ 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
244
+ 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
245
+ 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
246
+ 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
247
+ 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
248
+ 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
249
+ 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
250
+ 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
251
+ 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
252
+ 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
253
+ 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
254
+ 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
255
+ 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
256
+ 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
257
+ 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
258
+ 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
259
+ 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
260
+ 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
261
+ 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
262
+ 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
263
+ 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
264
+ 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
265
+ 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
266
+ 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
267
+ 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
268
+ 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
269
+ 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
270
+ 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
271
+ 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
272
+ 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
273
+ 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
274
+ 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
275
+ 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
276
+ 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
277
+ 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
278
+ 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
279
+ 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
280
+ 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
281
+ 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
282
+ 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
283
+ 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
284
+ 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
285
+ 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
286
+ 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
287
+ 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
288
+ 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
289
+ 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
290
+ 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
291
+ );
292
+
293
+ /**
294
+ * Inverse key expansion randomization table.
295
+ *
296
+ * @see self::setKey()
297
+ * @var array
298
+ * @access private
299
+ */
300
+ var $invpitable = array(
301
+ 0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66,
302
+ 0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4,
303
+ 0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20,
304
+ 0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53,
305
+ 0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68,
306
+ 0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B,
307
+ 0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12,
308
+ 0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB,
309
+ 0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3,
310
+ 0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26,
311
+ 0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67,
312
+ 0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB,
313
+ 0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC,
314
+ 0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60,
315
+ 0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7,
316
+ 0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD,
317
+ 0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24,
318
+ 0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31,
319
+ 0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE,
320
+ 0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99,
321
+ 0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C,
322
+ 0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA,
323
+ 0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35,
324
+ 0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61,
325
+ 0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72,
326
+ 0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3,
327
+ 0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F,
328
+ 0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9,
329
+ 0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77,
330
+ 0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75,
331
+ 0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87,
332
+ 0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
333
+ );
334
+
335
+ /**
336
+ * Test for engine validity
337
+ *
338
+ * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
339
+ *
340
+ * @see Crypt_Base::Crypt_Base()
341
+ * @param int $engine
342
+ * @access public
343
+ * @return bool
344
+ */
345
+ function isValidEngine($engine)
346
+ {
347
+ switch ($engine) {
348
+ case CRYPT_ENGINE_OPENSSL:
349
+ if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
350
+ return false;
351
+ }
352
+ $this->cipher_name_openssl_ecb = 'rc2-ecb';
353
+ $this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
354
+ }
355
+
356
+ return parent::isValidEngine($engine);
357
+ }
358
+
359
+ /**
360
+ * Sets the key length.
361
+ *
362
+ * Valid key lengths are 8 to 1024.
363
+ * Calling this function after setting the key has no effect until the next
364
+ * Crypt_RC2::setKey() call.
365
+ *
366
+ * @access public
367
+ * @param int $length in bits
368
+ */
369
+ function setKeyLength($length)
370
+ {
371
+ if ($length < 8) {
372
+ $this->default_key_length = 8;
373
+ } elseif ($length > 1024) {
374
+ $this->default_key_length = 128;
375
+ } else {
376
+ $this->default_key_length = $length;
377
+ }
378
+ $this->current_key_length = $this->default_key_length;
379
+
380
+ parent::setKeyLength($length);
381
+ }
382
+
383
+ /**
384
+ * Returns the current key length
385
+ *
386
+ * @access public
387
+ * @return int
388
+ */
389
+ function getKeyLength()
390
+ {
391
+ return $this->current_key_length;
392
+ }
393
+
394
+ /**
395
+ * Sets the key.
396
+ *
397
+ * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
398
+ * strlen($key) <= 128), however, we only use the first 128 bytes if $key
399
+ * has more then 128 bytes in it, and set $key to a single null byte if
400
+ * it is empty.
401
+ *
402
+ * If the key is not explicitly set, it'll be assumed to be a single
403
+ * null byte.
404
+ *
405
+ * @see Crypt_Base::setKey()
406
+ * @access public
407
+ * @param string $key
408
+ * @param int $t1 optional Effective key length in bits.
409
+ */
410
+ function setKey($key, $t1 = 0)
411
+ {
412
+ $this->orig_key = $key;
413
+
414
+ if ($t1 <= 0) {
415
+ $t1 = $this->default_key_length;
416
+ } elseif ($t1 > 1024) {
417
+ $t1 = 1024;
418
+ }
419
+ $this->current_key_length = $t1;
420
+ // Key byte count should be 1..128.
421
+ $key = strlen($key) ? substr($key, 0, 128) : "\x00";
422
+ $t = strlen($key);
423
+
424
+ // The mcrypt RC2 implementation only supports effective key length
425
+ // of 1024 bits. It is however possible to handle effective key
426
+ // lengths in range 1..1024 by expanding the key and applying
427
+ // inverse pitable mapping to the first byte before submitting it
428
+ // to mcrypt.
429
+
430
+ // Key expansion.
431
+ $l = array_values(unpack('C*', $key));
432
+ $t8 = ($t1 + 7) >> 3;
433
+ $tm = 0xFF >> (8 * $t8 - $t1);
434
+
435
+ // Expand key.
436
+ $pitable = $this->pitable;
437
+ for ($i = $t; $i < 128; $i++) {
438
+ $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
439
+ }
440
+ $i = 128 - $t8;
441
+ $l[$i] = $pitable[$l[$i] & $tm];
442
+ while ($i--) {
443
+ $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
444
+ }
445
+
446
+ // Prepare the key for mcrypt.
447
+ $l[0] = $this->invpitable[$l[0]];
448
+ array_unshift($l, 'C*');
449
+
450
+ parent::setKey(call_user_func_array('pack', $l));
451
+ }
452
+
453
+ /**
454
+ * Encrypts a message.
455
+ *
456
+ * Mostly a wrapper for Crypt_Base::encrypt, with some additional OpenSSL handling code
457
+ *
458
+ * @see self::decrypt()
459
+ * @access public
460
+ * @param string $plaintext
461
+ * @return string $ciphertext
462
+ */
463
+ function encrypt($plaintext)
464
+ {
465
+ if ($this->engine == CRYPT_ENGINE_OPENSSL) {
466
+ $temp = $this->key;
467
+ $this->key = $this->orig_key;
468
+ $result = parent::encrypt($plaintext);
469
+ $this->key = $temp;
470
+ return $result;
471
+ }
472
+
473
+ return parent::encrypt($plaintext);
474
+ }
475
+
476
+ /**
477
+ * Decrypts a message.
478
+ *
479
+ * Mostly a wrapper for Crypt_Base::decrypt, with some additional OpenSSL handling code
480
+ *
481
+ * @see self::encrypt()
482
+ * @access public
483
+ * @param string $ciphertext
484
+ * @return string $plaintext
485
+ */
486
+ function decrypt($ciphertext)
487
+ {
488
+ if ($this->engine == CRYPT_ENGINE_OPENSSL) {
489
+ $temp = $this->key;
490
+ $this->key = $this->orig_key;
491
+ $result = parent::decrypt($ciphertext);
492
+ $this->key = $temp;
493
+ return $result;
494
+ }
495
+
496
+ return parent::decrypt($ciphertext);
497
+ }
498
+
499
+ /**
500
+ * Encrypts a block
501
+ *
502
+ * @see Crypt_Base::_encryptBlock()
503
+ * @see Crypt_Base::encrypt()
504
+ * @access private
505
+ * @param string $in
506
+ * @return string
507
+ */
508
+ function _encryptBlock($in)
509
+ {
510
+ list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
511
+ $keys = $this->keys;
512
+ $limit = 20;
513
+ $actions = array($limit => 44, 44 => 64);
514
+ $j = 0;
515
+
516
+ for (;;) {
517
+ // Mixing round.
518
+ $r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
519
+ $r0 |= $r0 >> 16;
520
+ $r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
521
+ $r1 |= $r1 >> 16;
522
+ $r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
523
+ $r2 |= $r2 >> 16;
524
+ $r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
525
+ $r3 |= $r3 >> 16;
526
+
527
+ if ($j === $limit) {
528
+ if ($limit === 64) {
529
+ break;
530
+ }
531
+
532
+ // Mashing round.
533
+ $r0 += $keys[$r3 & 0x3F];
534
+ $r1 += $keys[$r0 & 0x3F];
535
+ $r2 += $keys[$r1 & 0x3F];
536
+ $r3 += $keys[$r2 & 0x3F];
537
+ $limit = $actions[$limit];
538
+ }
539
+ }
540
+
541
+ return pack('vvvv', $r0, $r1, $r2, $r3);
542
+ }
543
+
544
+ /**
545
+ * Decrypts a block
546
+ *
547
+ * @see Crypt_Base::_decryptBlock()
548
+ * @see Crypt_Base::decrypt()
549
+ * @access private
550
+ * @param string $in
551
+ * @return string
552
+ */
553
+ function _decryptBlock($in)
554
+ {
555
+ list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
556
+ $keys = $this->keys;
557
+ $limit = 44;
558
+ $actions = array($limit => 20, 20 => 0);
559
+ $j = 64;
560
+
561
+ for (;;) {
562
+ // R-mixing round.
563
+ $r3 = ($r3 | ($r3 << 16)) >> 5;
564
+ $r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
565
+ $r2 = ($r2 | ($r2 << 16)) >> 3;
566
+ $r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
567
+ $r1 = ($r1 | ($r1 << 16)) >> 2;
568
+ $r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
569
+ $r0 = ($r0 | ($r0 << 16)) >> 1;
570
+ $r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
571
+
572
+ if ($j === $limit) {
573
+ if ($limit === 0) {
574
+ break;
575
+ }
576
+
577
+ // R-mashing round.
578
+ $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
579
+ $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
580
+ $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
581
+ $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;
582
+ $limit = $actions[$limit];
583
+ }
584
+ }
585
+
586
+ return pack('vvvv', $r0, $r1, $r2, $r3);
587
+ }
588
+
589
+ /**
590
+ * Setup the CRYPT_ENGINE_MCRYPT $engine
591
+ *
592
+ * @see Crypt_Base::_setupMcrypt()
593
+ * @access private
594
+ */
595
+ function _setupMcrypt()
596
+ {
597
+ if (!isset($this->key)) {
598
+ $this->setKey('');
599
+ }
600
+
601
+ parent::_setupMcrypt();
602
+ }
603
+
604
+ /**
605
+ * Creates the key schedule
606
+ *
607
+ * @see Crypt_Base::_setupKey()
608
+ * @access private
609
+ */
610
+ function _setupKey()
611
+ {
612
+ if (!isset($this->key)) {
613
+ $this->setKey('');
614
+ }
615
+
616
+ // Key has already been expanded in Crypt_RC2::setKey():
617
+ // Only the first value must be altered.
618
+ $l = unpack('Ca/Cb/v*', $this->key);
619
+ array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8));
620
+ unset($l['a']);
621
+ unset($l['b']);
622
+ $this->keys = $l;
623
+ }
624
+
625
+ /**
626
+ * Setup the performance-optimized function for de/encrypt()
627
+ *
628
+ * @see Crypt_Base::_setupInlineCrypt()
629
+ * @access private
630
+ */
631
+ function _setupInlineCrypt()
632
+ {
633
+ $lambda_functions = &Crypt_RC2::_getLambdaFunctions();
634
+
635
+ // The first 10 generated $lambda_functions will use the $keys hardcoded as integers
636
+ // for the mixing rounds, for better inline crypt performance [~20% faster].
637
+ // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
638
+ // (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
639
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
640
+
641
+ // Generation of a unique hash for our generated code
642
+ $code_hash = "Crypt_RC2, {$this->mode}";
643
+ if ($gen_hi_opt_code) {
644
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
645
+ }
646
+
647
+ // Is there a re-usable $lambda_functions in there?
648
+ // If not, we have to create it.
649
+ if (!isset($lambda_functions[$code_hash])) {
650
+ // Init code for both, encrypt and decrypt.
651
+ $init_crypt = '$keys = $self->keys;';
652
+
653
+ switch (true) {
654
+ case $gen_hi_opt_code:
655
+ $keys = $this->keys;
656
+ default:
657
+ $keys = array();
658
+ foreach ($this->keys as $k => $v) {
659
+ $keys[$k] = '$keys[' . $k . ']';
660
+ }
661
+ }
662
+
663
+ // $in is the current 8 bytes block which has to be en/decrypt
664
+ $encrypt_block = $decrypt_block = '
665
+ $in = unpack("v4", $in);
666
+ $r0 = $in[1];
667
+ $r1 = $in[2];
668
+ $r2 = $in[3];
669
+ $r3 = $in[4];
670
+ ';
671
+
672
+ // Create code for encryption.
673
+ $limit = 20;
674
+ $actions = array($limit => 44, 44 => 64);
675
+ $j = 0;
676
+
677
+ for (;;) {
678
+ // Mixing round.
679
+ $encrypt_block .= '
680
+ $r0 = (($r0 + ' . $keys[$j++] . ' +
681
+ ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
682
+ $r0 |= $r0 >> 16;
683
+ $r1 = (($r1 + ' . $keys[$j++] . ' +
684
+ ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
685
+ $r1 |= $r1 >> 16;
686
+ $r2 = (($r2 + ' . $keys[$j++] . ' +
687
+ ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
688
+ $r2 |= $r2 >> 16;
689
+ $r3 = (($r3 + ' . $keys[$j++] . ' +
690
+ ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
691
+ $r3 |= $r3 >> 16;';
692
+
693
+ if ($j === $limit) {
694
+ if ($limit === 64) {
695
+ break;
696
+ }
697
+
698
+ // Mashing round.
699
+ $encrypt_block .= '
700
+ $r0 += $keys[$r3 & 0x3F];
701
+ $r1 += $keys[$r0 & 0x3F];
702
+ $r2 += $keys[$r1 & 0x3F];
703
+ $r3 += $keys[$r2 & 0x3F];';
704
+ $limit = $actions[$limit];
705
+ }
706
+ }
707
+
708
+ $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
709
+
710
+ // Create code for decryption.
711
+ $limit = 44;
712
+ $actions = array($limit => 20, 20 => 0);
713
+ $j = 64;
714
+
715
+ for (;;) {
716
+ // R-mixing round.
717
+ $decrypt_block .= '
718
+ $r3 = ($r3 | ($r3 << 16)) >> 5;
719
+ $r3 = ($r3 - ' . $keys[--$j] . ' -
720
+ ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
721
+ $r2 = ($r2 | ($r2 << 16)) >> 3;
722
+ $r2 = ($r2 - ' . $keys[--$j] . ' -
723
+ ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
724
+ $r1 = ($r1 | ($r1 << 16)) >> 2;
725
+ $r1 = ($r1 - ' . $keys[--$j] . ' -
726
+ ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
727
+ $r0 = ($r0 | ($r0 << 16)) >> 1;
728
+ $r0 = ($r0 - ' . $keys[--$j] . ' -
729
+ ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
730
+
731
+ if ($j === $limit) {
732
+ if ($limit === 0) {
733
+ break;
734
+ }
735
+
736
+ // R-mashing round.
737
+ $decrypt_block .= '
738
+ $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
739
+ $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
740
+ $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
741
+ $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
742
+ $limit = $actions[$limit];
743
+ }
744
+ }
745
+
746
+ $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
747
+
748
+ // Creates the inline-crypt function
749
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
750
+ array(
751
+ 'init_crypt' => $init_crypt,
752
+ 'encrypt_block' => $encrypt_block,
753
+ 'decrypt_block' => $decrypt_block
754
+ )
755
+ );
756
+ }
757
+
758
+ // Set the inline-crypt function as callback in: $this->inline_crypt
759
+ $this->inline_crypt = $lambda_functions[$code_hash];
760
+ }
761
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of RC4.
5
+ *
6
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * Useful resources are as follows:
11
+ *
12
+ * - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
13
+ * - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
14
+ *
15
+ * RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
16
+ * ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
17
+ *
18
+ * Here's a short example of how to use this library:
19
+ * <code>
20
+ * <?php
21
+ * include 'Crypt/RC4.php';
22
+ *
23
+ * $rc4 = new Crypt_RC4();
24
+ *
25
+ * $rc4->setKey('abcdefgh');
26
+ *
27
+ * $size = 10 * 1024;
28
+ * $plaintext = '';
29
+ * for ($i = 0; $i < $size; $i++) {
30
+ * $plaintext.= 'a';
31
+ * }
32
+ *
33
+ * echo $rc4->decrypt($rc4->encrypt($plaintext));
34
+ * ?>
35
+ * </code>
36
+ *
37
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
38
+ * of this software and associated documentation files (the "Software"), to deal
39
+ * in the Software without restriction, including without limitation the rights
40
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41
+ * copies of the Software, and to permit persons to whom the Software is
42
+ * furnished to do so, subject to the following conditions:
43
+ *
44
+ * The above copyright notice and this permission notice shall be included in
45
+ * all copies or substantial portions of the Software.
46
+ *
47
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
53
+ * THE SOFTWARE.
54
+ *
55
+ * @category Crypt
56
+ * @package Crypt_RC4
57
+ * @author Jim Wigginton <terrafrost@php.net>
58
+ * @copyright 2007 Jim Wigginton
59
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
60
+ * @link http://phpseclib.sourceforge.net
61
+ */
62
+
63
+ /**
64
+ * Include Crypt_Base
65
+ *
66
+ * Base cipher class
67
+ */
68
+ if (!class_exists('Crypt_Base')) {
69
+ include_once 'Base.php';
70
+ }
71
+
72
+ /**#@+
73
+ * @access private
74
+ * @see self::_crypt()
75
+ */
76
+ define('CRYPT_RC4_ENCRYPT', 0);
77
+ define('CRYPT_RC4_DECRYPT', 1);
78
+ /**#@-*/
79
+
80
+ /**
81
+ * Pure-PHP implementation of RC4.
82
+ *
83
+ * @package Crypt_RC4
84
+ * @author Jim Wigginton <terrafrost@php.net>
85
+ * @access public
86
+ */
87
+ class Crypt_RC4 extends Crypt_Base
88
+ {
89
+ /**
90
+ * Block Length of the cipher
91
+ *
92
+ * RC4 is a stream cipher
93
+ * so we the block_size to 0
94
+ *
95
+ * @see Crypt_Base::block_size
96
+ * @var int
97
+ * @access private
98
+ */
99
+ var $block_size = 0;
100
+
101
+ /**
102
+ * Key Length (in bytes)
103
+ *
104
+ * @see Crypt_RC4::setKeyLength()
105
+ * @var int
106
+ * @access private
107
+ */
108
+ var $key_length = 128; // = 1024 bits
109
+
110
+ /**
111
+ * The namespace used by the cipher for its constants.
112
+ *
113
+ * @see Crypt_Base::const_namespace
114
+ * @var string
115
+ * @access private
116
+ */
117
+ var $const_namespace = 'RC4';
118
+
119
+ /**
120
+ * The mcrypt specific name of the cipher
121
+ *
122
+ * @see Crypt_Base::cipher_name_mcrypt
123
+ * @var string
124
+ * @access private
125
+ */
126
+ var $cipher_name_mcrypt = 'arcfour';
127
+
128
+ /**
129
+ * Holds whether performance-optimized $inline_crypt() can/should be used.
130
+ *
131
+ * @see Crypt_Base::inline_crypt
132
+ * @var mixed
133
+ * @access private
134
+ */
135
+ var $use_inline_crypt = false; // currently not available
136
+
137
+ /**
138
+ * The Key
139
+ *
140
+ * @see self::setKey()
141
+ * @var string
142
+ * @access private
143
+ */
144
+ var $key = "\0";
145
+
146
+ /**
147
+ * The Key Stream for decryption and encryption
148
+ *
149
+ * @see self::setKey()
150
+ * @var array
151
+ * @access private
152
+ */
153
+ var $stream;
154
+
155
+ /**
156
+ * Default Constructor.
157
+ *
158
+ * Determines whether or not the mcrypt extension should be used.
159
+ *
160
+ * @see Crypt_Base::Crypt_Base()
161
+ * @return Crypt_RC4
162
+ * @access public
163
+ */
164
+ function __construct()
165
+ {
166
+ parent::__construct(CRYPT_MODE_STREAM);
167
+ }
168
+
169
+ /**
170
+ * PHP4 compatible Default Constructor.
171
+ *
172
+ * @see self::__construct()
173
+ * @access public
174
+ */
175
+ function Crypt_RC4()
176
+ {
177
+ $this->__construct();
178
+ }
179
+
180
+ /**
181
+ * Test for engine validity
182
+ *
183
+ * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
184
+ *
185
+ * @see Crypt_Base::Crypt_Base()
186
+ * @param int $engine
187
+ * @access public
188
+ * @return bool
189
+ */
190
+ function isValidEngine($engine)
191
+ {
192
+ if ($engine == CRYPT_ENGINE_OPENSSL) {
193
+ $this->cipher_name_openssl = 'rc4-40';
194
+ }
195
+
196
+ return parent::isValidEngine($engine);
197
+ }
198
+
199
+ /**
200
+ * Dummy function.
201
+ *
202
+ * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
203
+ * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
204
+ * calling setKey().
205
+ *
206
+ * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
207
+ * the IV's are relatively easy to predict, an attack described by
208
+ * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
209
+ * can be used to quickly guess at the rest of the key. The following links elaborate:
210
+ *
211
+ * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
212
+ * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
213
+ *
214
+ * @param string $iv
215
+ * @see self::setKey()
216
+ * @access public
217
+ */
218
+ function setIV($iv)
219
+ {
220
+ }
221
+
222
+ /**
223
+ * Sets the key length
224
+ *
225
+ * Keys can be between 1 and 256 bytes long.
226
+ *
227
+ * @access public
228
+ * @param int $length
229
+ */
230
+ function setKeyLength($length)
231
+ {
232
+ if ($length < 8) {
233
+ $this->key_length = 1;
234
+ } elseif ($length > 2048) {
235
+ $this->key_length = 256;
236
+ } else {
237
+ $this->key_length = $length >> 3;
238
+ }
239
+
240
+ parent::setKeyLength($length);
241
+ }
242
+
243
+ /**
244
+ * Encrypts a message.
245
+ *
246
+ * @see Crypt_Base::decrypt()
247
+ * @see self::_crypt()
248
+ * @access public
249
+ * @param string $plaintext
250
+ * @return string $ciphertext
251
+ */
252
+ function encrypt($plaintext)
253
+ {
254
+ if ($this->engine != CRYPT_ENGINE_INTERNAL) {
255
+ return parent::encrypt($plaintext);
256
+ }
257
+ return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
258
+ }
259
+
260
+ /**
261
+ * Decrypts a message.
262
+ *
263
+ * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
264
+ * At least if the continuous buffer is disabled.
265
+ *
266
+ * @see Crypt_Base::encrypt()
267
+ * @see self::_crypt()
268
+ * @access public
269
+ * @param string $ciphertext
270
+ * @return string $plaintext
271
+ */
272
+ function decrypt($ciphertext)
273
+ {
274
+ if ($this->engine != CRYPT_ENGINE_INTERNAL) {
275
+ return parent::decrypt($ciphertext);
276
+ }
277
+ return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
278
+ }
279
+
280
+
281
+ /**
282
+ * Setup the key (expansion)
283
+ *
284
+ * @see Crypt_Base::_setupKey()
285
+ * @access private
286
+ */
287
+ function _setupKey()
288
+ {
289
+ $key = $this->key;
290
+ $keyLength = strlen($key);
291
+ $keyStream = range(0, 255);
292
+ $j = 0;
293
+ for ($i = 0; $i < 256; $i++) {
294
+ $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
295
+ $temp = $keyStream[$i];
296
+ $keyStream[$i] = $keyStream[$j];
297
+ $keyStream[$j] = $temp;
298
+ }
299
+
300
+ $this->stream = array();
301
+ $this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
302
+ 0, // index $i
303
+ 0, // index $j
304
+ $keyStream
305
+ );
306
+ }
307
+
308
+ /**
309
+ * Encrypts or decrypts a message.
310
+ *
311
+ * @see self::encrypt()
312
+ * @see self::decrypt()
313
+ * @access private
314
+ * @param string $text
315
+ * @param int $mode
316
+ * @return string $text
317
+ */
318
+ function _crypt($text, $mode)
319
+ {
320
+ if ($this->changed) {
321
+ $this->_setup();
322
+ $this->changed = false;
323
+ }
324
+
325
+ $stream = &$this->stream[$mode];
326
+ if ($this->continuousBuffer) {
327
+ $i = &$stream[0];
328
+ $j = &$stream[1];
329
+ $keyStream = &$stream[2];
330
+ } else {
331
+ $i = $stream[0];
332
+ $j = $stream[1];
333
+ $keyStream = $stream[2];
334
+ }
335
+
336
+ $len = strlen($text);
337
+ for ($k = 0; $k < $len; ++$k) {
338
+ $i = ($i + 1) & 255;
339
+ $ksi = $keyStream[$i];
340
+ $j = ($j + $ksi) & 255;
341
+ $ksj = $keyStream[$j];
342
+
343
+ $keyStream[$i] = $ksj;
344
+ $keyStream[$j] = $ksi;
345
+ $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
346
+ }
347
+
348
+ return $text;
349
+ }
350
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php ADDED
@@ -0,0 +1,3133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP PKCS#1 (v2.1) compliant implementation of RSA.
5
+ *
6
+ * PHP versions 4 and 5
7
+ *
8
+ * Here's an example of how to encrypt and decrypt text with this library:
9
+ * <code>
10
+ * <?php
11
+ * include 'Crypt/RSA.php';
12
+ *
13
+ * $rsa = new Crypt_RSA();
14
+ * extract($rsa->createKey());
15
+ *
16
+ * $plaintext = 'terrafrost';
17
+ *
18
+ * $rsa->loadKey($privatekey);
19
+ * $ciphertext = $rsa->encrypt($plaintext);
20
+ *
21
+ * $rsa->loadKey($publickey);
22
+ * echo $rsa->decrypt($ciphertext);
23
+ * ?>
24
+ * </code>
25
+ *
26
+ * Here's an example of how to create signatures and verify signatures with this library:
27
+ * <code>
28
+ * <?php
29
+ * include 'Crypt/RSA.php';
30
+ *
31
+ * $rsa = new Crypt_RSA();
32
+ * extract($rsa->createKey());
33
+ *
34
+ * $plaintext = 'terrafrost';
35
+ *
36
+ * $rsa->loadKey($privatekey);
37
+ * $signature = $rsa->sign($plaintext);
38
+ *
39
+ * $rsa->loadKey($publickey);
40
+ * echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified';
41
+ * ?>
42
+ * </code>
43
+ *
44
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
45
+ * of this software and associated documentation files (the "Software"), to deal
46
+ * in the Software without restriction, including without limitation the rights
47
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
48
+ * copies of the Software, and to permit persons to whom the Software is
49
+ * furnished to do so, subject to the following conditions:
50
+ *
51
+ * The above copyright notice and this permission notice shall be included in
52
+ * all copies or substantial portions of the Software.
53
+ *
54
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
59
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
60
+ * THE SOFTWARE.
61
+ *
62
+ * @category Crypt
63
+ * @package Crypt_RSA
64
+ * @author Jim Wigginton <terrafrost@php.net>
65
+ * @copyright 2009 Jim Wigginton
66
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
67
+ * @link http://phpseclib.sourceforge.net
68
+ */
69
+
70
+ /**
71
+ * Include Crypt_Random
72
+ */
73
+ // the class_exists() will only be called if the crypt_random_string function hasn't been defined and
74
+ // will trigger a call to __autoload() if you're wanting to auto-load classes
75
+ // call function_exists() a second time to stop the include_once from being called outside
76
+ // of the auto loader
77
+ if (!function_exists('crypt_random_string')) {
78
+ include_once 'Random.php';
79
+ }
80
+
81
+ /**
82
+ * Include Crypt_Hash
83
+ */
84
+ if (!class_exists('Crypt_Hash')) {
85
+ include_once 'Hash.php';
86
+ }
87
+
88
+ /**#@+
89
+ * @access public
90
+ * @see self::encrypt()
91
+ * @see self::decrypt()
92
+ */
93
+ /**
94
+ * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
95
+ * (OAEP) for encryption / decryption.
96
+ *
97
+ * Uses sha1 by default.
98
+ *
99
+ * @see self::setHash()
100
+ * @see self::setMGFHash()
101
+ */
102
+ define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
103
+ /**
104
+ * Use PKCS#1 padding.
105
+ *
106
+ * Although CRYPT_RSA_ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards
107
+ * compatibility with protocols (like SSH-1) written before OAEP's introduction.
108
+ */
109
+ define('CRYPT_RSA_ENCRYPTION_PKCS1', 2);
110
+ /**
111
+ * Do not use any padding
112
+ *
113
+ * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
114
+ * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
115
+ */
116
+ define('CRYPT_RSA_ENCRYPTION_NONE', 3);
117
+ /**#@-*/
118
+
119
+ /**#@+
120
+ * @access public
121
+ * @see self::sign()
122
+ * @see self::verify()
123
+ * @see self::setHash()
124
+ */
125
+ /**
126
+ * Use the Probabilistic Signature Scheme for signing
127
+ *
128
+ * Uses sha1 by default.
129
+ *
130
+ * @see self::setSaltLength()
131
+ * @see self::setMGFHash()
132
+ */
133
+ define('CRYPT_RSA_SIGNATURE_PSS', 1);
134
+ /**
135
+ * Use the PKCS#1 scheme by default.
136
+ *
137
+ * Although CRYPT_RSA_SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards
138
+ * compatibility with protocols (like SSH-2) written before PSS's introduction.
139
+ */
140
+ define('CRYPT_RSA_SIGNATURE_PKCS1', 2);
141
+ /**#@-*/
142
+
143
+ /**#@+
144
+ * @access private
145
+ * @see self::createKey()
146
+ */
147
+ /**
148
+ * ASN1 Integer
149
+ */
150
+ define('CRYPT_RSA_ASN1_INTEGER', 2);
151
+ /**
152
+ * ASN1 Bit String
153
+ */
154
+ define('CRYPT_RSA_ASN1_BITSTRING', 3);
155
+ /**
156
+ * ASN1 Octet String
157
+ */
158
+ define('CRYPT_RSA_ASN1_OCTETSTRING', 4);
159
+ /**
160
+ * ASN1 Object Identifier
161
+ */
162
+ define('CRYPT_RSA_ASN1_OBJECT', 6);
163
+ /**
164
+ * ASN1 Sequence (with the constucted bit set)
165
+ */
166
+ define('CRYPT_RSA_ASN1_SEQUENCE', 48);
167
+ /**#@-*/
168
+
169
+ /**#@+
170
+ * @access private
171
+ * @see self::Crypt_RSA()
172
+ */
173
+ /**
174
+ * To use the pure-PHP implementation
175
+ */
176
+ define('CRYPT_RSA_MODE_INTERNAL', 1);
177
+ /**
178
+ * To use the OpenSSL library
179
+ *
180
+ * (if enabled; otherwise, the internal implementation will be used)
181
+ */
182
+ define('CRYPT_RSA_MODE_OPENSSL', 2);
183
+ /**#@-*/
184
+
185
+ /**
186
+ * Default openSSL configuration file.
187
+ */
188
+ define('CRYPT_RSA_OPENSSL_CONFIG', dirname(__FILE__) . '/../openssl.cnf');
189
+
190
+ /**#@+
191
+ * @access public
192
+ * @see self::createKey()
193
+ * @see self::setPrivateKeyFormat()
194
+ */
195
+ /**
196
+ * PKCS#1 formatted private key
197
+ *
198
+ * Used by OpenSSH
199
+ */
200
+ define('CRYPT_RSA_PRIVATE_FORMAT_PKCS1', 0);
201
+ /**
202
+ * PuTTY formatted private key
203
+ */
204
+ define('CRYPT_RSA_PRIVATE_FORMAT_PUTTY', 1);
205
+ /**
206
+ * XML formatted private key
207
+ */
208
+ define('CRYPT_RSA_PRIVATE_FORMAT_XML', 2);
209
+ /**
210
+ * PKCS#8 formatted private key
211
+ */
212
+ define('CRYPT_RSA_PRIVATE_FORMAT_PKCS8', 8);
213
+ /**#@-*/
214
+
215
+ /**#@+
216
+ * @access public
217
+ * @see self::createKey()
218
+ * @see self::setPublicKeyFormat()
219
+ */
220
+ /**
221
+ * Raw public key
222
+ *
223
+ * An array containing two Math_BigInteger objects.
224
+ *
225
+ * The exponent can be indexed with any of the following:
226
+ *
227
+ * 0, e, exponent, publicExponent
228
+ *
229
+ * The modulus can be indexed with any of the following:
230
+ *
231
+ * 1, n, modulo, modulus
232
+ */
233
+ define('CRYPT_RSA_PUBLIC_FORMAT_RAW', 3);
234
+ /**
235
+ * PKCS#1 formatted public key (raw)
236
+ *
237
+ * Used by File/X509.php
238
+ *
239
+ * Has the following header:
240
+ *
241
+ * -----BEGIN RSA PUBLIC KEY-----
242
+ *
243
+ * Analogous to ssh-keygen's pem format (as specified by -m)
244
+ */
245
+ define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 4);
246
+ define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW', 4);
247
+ /**
248
+ * XML formatted public key
249
+ */
250
+ define('CRYPT_RSA_PUBLIC_FORMAT_XML', 5);
251
+ /**
252
+ * OpenSSH formatted public key
253
+ *
254
+ * Place in $HOME/.ssh/authorized_keys
255
+ */
256
+ define('CRYPT_RSA_PUBLIC_FORMAT_OPENSSH', 6);
257
+ /**
258
+ * PKCS#1 formatted public key (encapsulated)
259
+ *
260
+ * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
261
+ *
262
+ * Has the following header:
263
+ *
264
+ * -----BEGIN PUBLIC KEY-----
265
+ *
266
+ * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
267
+ * is specific to private keys it's basically creating a DER-encoded wrapper
268
+ * for keys. This just extends that same concept to public keys (much like ssh-keygen)
269
+ */
270
+ define('CRYPT_RSA_PUBLIC_FORMAT_PKCS8', 7);
271
+ /**#@-*/
272
+
273
+ /**
274
+ * Pure-PHP PKCS#1 compliant implementation of RSA.
275
+ *
276
+ * @package Crypt_RSA
277
+ * @author Jim Wigginton <terrafrost@php.net>
278
+ * @access public
279
+ */
280
+ class Crypt_RSA
281
+ {
282
+ /**
283
+ * Precomputed Zero
284
+ *
285
+ * @var Math_BigInteger
286
+ * @access private
287
+ */
288
+ var $zero;
289
+
290
+ /**
291
+ * Precomputed One
292
+ *
293
+ * @var Math_BigInteger
294
+ * @access private
295
+ */
296
+ var $one;
297
+
298
+ /**
299
+ * Private Key Format
300
+ *
301
+ * @var int
302
+ * @access private
303
+ */
304
+ var $privateKeyFormat = CRYPT_RSA_PRIVATE_FORMAT_PKCS1;
305
+
306
+ /**
307
+ * Public Key Format
308
+ *
309
+ * @var int
310
+ * @access public
311
+ */
312
+ var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS8;
313
+
314
+ /**
315
+ * Modulus (ie. n)
316
+ *
317
+ * @var Math_BigInteger
318
+ * @access private
319
+ */
320
+ var $modulus;
321
+
322
+ /**
323
+ * Modulus length
324
+ *
325
+ * @var Math_BigInteger
326
+ * @access private
327
+ */
328
+ var $k;
329
+
330
+ /**
331
+ * Exponent (ie. e or d)
332
+ *
333
+ * @var Math_BigInteger
334
+ * @access private
335
+ */
336
+ var $exponent;
337
+
338
+ /**
339
+ * Primes for Chinese Remainder Theorem (ie. p and q)
340
+ *
341
+ * @var array
342
+ * @access private
343
+ */
344
+ var $primes;
345
+
346
+ /**
347
+ * Exponents for Chinese Remainder Theorem (ie. dP and dQ)
348
+ *
349
+ * @var array
350
+ * @access private
351
+ */
352
+ var $exponents;
353
+
354
+ /**
355
+ * Coefficients for Chinese Remainder Theorem (ie. qInv)
356
+ *
357
+ * @var array
358
+ * @access private
359
+ */
360
+ var $coefficients;
361
+
362
+ /**
363
+ * Hash name
364
+ *
365
+ * @var string
366
+ * @access private
367
+ */
368
+ var $hashName;
369
+
370
+ /**
371
+ * Hash function
372
+ *
373
+ * @var Crypt_Hash
374
+ * @access private
375
+ */
376
+ var $hash;
377
+
378
+ /**
379
+ * Length of hash function output
380
+ *
381
+ * @var int
382
+ * @access private
383
+ */
384
+ var $hLen;
385
+
386
+ /**
387
+ * Length of salt
388
+ *
389
+ * @var int
390
+ * @access private
391
+ */
392
+ var $sLen;
393
+
394
+ /**
395
+ * Hash function for the Mask Generation Function
396
+ *
397
+ * @var Crypt_Hash
398
+ * @access private
399
+ */
400
+ var $mgfHash;
401
+
402
+ /**
403
+ * Length of MGF hash function output
404
+ *
405
+ * @var int
406
+ * @access private
407
+ */
408
+ var $mgfHLen;
409
+
410
+ /**
411
+ * Encryption mode
412
+ *
413
+ * @var int
414
+ * @access private
415
+ */
416
+ var $encryptionMode = CRYPT_RSA_ENCRYPTION_OAEP;
417
+
418
+ /**
419
+ * Signature mode
420
+ *
421
+ * @var int
422
+ * @access private
423
+ */
424
+ var $signatureMode = CRYPT_RSA_SIGNATURE_PSS;
425
+
426
+ /**
427
+ * Public Exponent
428
+ *
429
+ * @var mixed
430
+ * @access private
431
+ */
432
+ var $publicExponent = false;
433
+
434
+ /**
435
+ * Password
436
+ *
437
+ * @var string
438
+ * @access private
439
+ */
440
+ var $password = false;
441
+
442
+ /**
443
+ * Components
444
+ *
445
+ * For use with parsing XML formatted keys. PHP's XML Parser functions use utilized - instead of PHP's DOM functions -
446
+ * because PHP's XML Parser functions work on PHP4 whereas PHP's DOM functions - although surperior - don't.
447
+ *
448
+ * @see self::_start_element_handler()
449
+ * @var array
450
+ * @access private
451
+ */
452
+ var $components = array();
453
+
454
+ /**
455
+ * Current String
456
+ *
457
+ * For use with parsing XML formatted keys.
458
+ *
459
+ * @see self::_character_handler()
460
+ * @see self::_stop_element_handler()
461
+ * @var mixed
462
+ * @access private
463
+ */
464
+ var $current;
465
+
466
+ /**
467
+ * OpenSSL configuration file name.
468
+ *
469
+ * Set to null to use system configuration file.
470
+ * @see self::createKey()
471
+ * @var mixed
472
+ * @Access public
473
+ */
474
+ var $configFile;
475
+
476
+ /**
477
+ * Public key comment field.
478
+ *
479
+ * @var string
480
+ * @access private
481
+ */
482
+ var $comment = 'phpseclib-generated-key';
483
+
484
+ /**
485
+ * The constructor
486
+ *
487
+ * If you want to make use of the openssl extension, you'll need to set the mode manually, yourself. The reason
488
+ * Crypt_RSA doesn't do it is because OpenSSL doesn't fail gracefully. openssl_pkey_new(), in particular, requires
489
+ * openssl.cnf be present somewhere and, unfortunately, the only real way to find out is too late.
490
+ *
491
+ * @return Crypt_RSA
492
+ * @access public
493
+ */
494
+ function __construct()
495
+ {
496
+ if (!class_exists('Math_BigInteger')) {
497
+ include_once 'Math/BigInteger.php';
498
+ }
499
+
500
+ $this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
501
+
502
+ if (!defined('CRYPT_RSA_MODE')) {
503
+ switch (true) {
504
+ // Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
505
+ // Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
506
+ // can't use OpenSSL it can be pretty trivially assumed, then, that Crypt/RSA can't either.
507
+ case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'):
508
+ define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
509
+ break;
510
+ // openssl_pkey_get_details - which is used in the only place Crypt/RSA.php uses OpenSSL - was introduced in PHP 5.2.0
511
+ case !function_exists('openssl_pkey_get_details'):
512
+ define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
513
+ break;
514
+ case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>=') && file_exists($this->configFile):
515
+ // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
516
+ ob_start();
517
+ @phpinfo();
518
+ $content = ob_get_contents();
519
+ ob_end_clean();
520
+
521
+ preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
522
+
523
+ $versions = array();
524
+ if (!empty($matches[1])) {
525
+ for ($i = 0; $i < count($matches[1]); $i++) {
526
+ $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
527
+
528
+ // Remove letter part in OpenSSL version
529
+ if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
530
+ $versions[$matches[1][$i]] = $fullVersion;
531
+ } else {
532
+ $versions[$matches[1][$i]] = $m[0];
533
+ }
534
+ }
535
+ }
536
+
537
+ // it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
538
+ switch (true) {
539
+ case !isset($versions['Header']):
540
+ case !isset($versions['Library']):
541
+ case $versions['Header'] == $versions['Library']:
542
+ case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0:
543
+ define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL);
544
+ break;
545
+ default:
546
+ define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
547
+ define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
548
+ }
549
+ break;
550
+ default:
551
+ define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
552
+ }
553
+ }
554
+
555
+ $this->zero = new Math_BigInteger();
556
+ $this->one = new Math_BigInteger(1);
557
+
558
+ $this->hash = new Crypt_Hash('sha1');
559
+ $this->hLen = $this->hash->getLength();
560
+ $this->hashName = 'sha1';
561
+ $this->mgfHash = new Crypt_Hash('sha1');
562
+ $this->mgfHLen = $this->mgfHash->getLength();
563
+ }
564
+
565
+ /**
566
+ * PHP4 compatible Default Constructor.
567
+ *
568
+ * @see self::__construct()
569
+ * @access public
570
+ */
571
+ function Crypt_RSA()
572
+ {
573
+ $this->__construct();
574
+ }
575
+
576
+ /**
577
+ * Create public / private key pair
578
+ *
579
+ * Returns an array with the following three elements:
580
+ * - 'privatekey': The private key.
581
+ * - 'publickey': The public key.
582
+ * - 'partialkey': A partially computed key (if the execution time exceeded $timeout).
583
+ * Will need to be passed back to Crypt_RSA::createKey() as the third parameter for further processing.
584
+ *
585
+ * @access public
586
+ * @param int $bits
587
+ * @param int $timeout
588
+ * @param Math_BigInteger $p
589
+ */
590
+ function createKey($bits = 1024, $timeout = false, $partial = array())
591
+ {
592
+ if (!defined('CRYPT_RSA_EXPONENT')) {
593
+ // http://en.wikipedia.org/wiki/65537_%28number%29
594
+ define('CRYPT_RSA_EXPONENT', '65537');
595
+ }
596
+ // per <http://cseweb.ucsd.edu/~hovav/dist/survey.pdf#page=5>, this number ought not result in primes smaller
597
+ // than 256 bits. as a consequence if the key you're trying to create is 1024 bits and you've set CRYPT_RSA_SMALLEST_PRIME
598
+ // to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). at least if
599
+ // CRYPT_RSA_MODE is set to CRYPT_RSA_MODE_INTERNAL. if CRYPT_RSA_MODE is set to CRYPT_RSA_MODE_OPENSSL then
600
+ // CRYPT_RSA_SMALLEST_PRIME is ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key
601
+ // generation when there's a chance neither gmp nor OpenSSL are installed)
602
+ if (!defined('CRYPT_RSA_SMALLEST_PRIME')) {
603
+ define('CRYPT_RSA_SMALLEST_PRIME', 4096);
604
+ }
605
+
606
+ // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
607
+ if (CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) {
608
+ $config = array();
609
+ if (isset($this->configFile)) {
610
+ $config['config'] = $this->configFile;
611
+ }
612
+ $rsa = openssl_pkey_new(array('private_key_bits' => $bits) + $config);
613
+ openssl_pkey_export($rsa, $privatekey, null, $config);
614
+ $publickey = openssl_pkey_get_details($rsa);
615
+ $publickey = $publickey['key'];
616
+
617
+ $privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1)));
618
+ $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1)));
619
+
620
+ // clear the buffer of error strings stemming from a minimalistic openssl.cnf
621
+ while (openssl_error_string() !== false) {
622
+ }
623
+
624
+ return array(
625
+ 'privatekey' => $privatekey,
626
+ 'publickey' => $publickey,
627
+ 'partialkey' => false
628
+ );
629
+ }
630
+
631
+ static $e;
632
+ if (!isset($e)) {
633
+ $e = new Math_BigInteger(CRYPT_RSA_EXPONENT);
634
+ }
635
+
636
+ extract($this->_generateMinMax($bits));
637
+ $absoluteMin = $min;
638
+ $temp = $bits >> 1; // divide by two to see how many bits P and Q would be
639
+ if ($temp > CRYPT_RSA_SMALLEST_PRIME) {
640
+ $num_primes = floor($bits / CRYPT_RSA_SMALLEST_PRIME);
641
+ $temp = CRYPT_RSA_SMALLEST_PRIME;
642
+ } else {
643
+ $num_primes = 2;
644
+ }
645
+ extract($this->_generateMinMax($temp + $bits % $temp));
646
+ $finalMax = $max;
647
+ extract($this->_generateMinMax($temp));
648
+
649
+ $generator = new Math_BigInteger();
650
+
651
+ $n = $this->one->copy();
652
+ if (!empty($partial)) {
653
+ extract(unserialize($partial));
654
+ } else {
655
+ $exponents = $coefficients = $primes = array();
656
+ $lcm = array(
657
+ 'top' => $this->one->copy(),
658
+ 'bottom' => false
659
+ );
660
+ }
661
+
662
+ $start = time();
663
+ $i0 = count($primes) + 1;
664
+
665
+ do {
666
+ for ($i = $i0; $i <= $num_primes; $i++) {
667
+ if ($timeout !== false) {
668
+ $timeout-= time() - $start;
669
+ $start = time();
670
+ if ($timeout <= 0) {
671
+ return array(
672
+ 'privatekey' => '',
673
+ 'publickey' => '',
674
+ 'partialkey' => serialize(array(
675
+ 'primes' => $primes,
676
+ 'coefficients' => $coefficients,
677
+ 'lcm' => $lcm,
678
+ 'exponents' => $exponents
679
+ ))
680
+ );
681
+ }
682
+ }
683
+
684
+ if ($i == $num_primes) {
685
+ list($min, $temp) = $absoluteMin->divide($n);
686
+ if (!$temp->equals($this->zero)) {
687
+ $min = $min->add($this->one); // ie. ceil()
688
+ }
689
+ $primes[$i] = $generator->randomPrime($min, $finalMax, $timeout);
690
+ } else {
691
+ $primes[$i] = $generator->randomPrime($min, $max, $timeout);
692
+ }
693
+
694
+ if ($primes[$i] === false) { // if we've reached the timeout
695
+ if (count($primes) > 1) {
696
+ $partialkey = '';
697
+ } else {
698
+ array_pop($primes);
699
+ $partialkey = serialize(array(
700
+ 'primes' => $primes,
701
+ 'coefficients' => $coefficients,
702
+ 'lcm' => $lcm,
703
+ 'exponents' => $exponents
704
+ ));
705
+ }
706
+
707
+ return array(
708
+ 'privatekey' => '',
709
+ 'publickey' => '',
710
+ 'partialkey' => $partialkey
711
+ );
712
+ }
713
+
714
+ // the first coefficient is calculated differently from the rest
715
+ // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1])
716
+ if ($i > 2) {
717
+ $coefficients[$i] = $n->modInverse($primes[$i]);
718
+ }
719
+
720
+ $n = $n->multiply($primes[$i]);
721
+
722
+ $temp = $primes[$i]->subtract($this->one);
723
+
724
+ // textbook RSA implementations use Euler's totient function instead of the least common multiple.
725
+ // see http://en.wikipedia.org/wiki/Euler%27s_totient_function
726
+ $lcm['top'] = $lcm['top']->multiply($temp);
727
+ $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp);
728
+
729
+ $exponents[$i] = $e->modInverse($temp);
730
+ }
731
+
732
+ list($temp) = $lcm['top']->divide($lcm['bottom']);
733
+ $gcd = $temp->gcd($e);
734
+ $i0 = 1;
735
+ } while (!$gcd->equals($this->one));
736
+
737
+ $d = $e->modInverse($temp);
738
+
739
+ $coefficients[2] = $primes[2]->modInverse($primes[1]);
740
+
741
+ // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.2>:
742
+ // RSAPrivateKey ::= SEQUENCE {
743
+ // version Version,
744
+ // modulus INTEGER, -- n
745
+ // publicExponent INTEGER, -- e
746
+ // privateExponent INTEGER, -- d
747
+ // prime1 INTEGER, -- p
748
+ // prime2 INTEGER, -- q
749
+ // exponent1 INTEGER, -- d mod (p-1)
750
+ // exponent2 INTEGER, -- d mod (q-1)
751
+ // coefficient INTEGER, -- (inverse of q) mod p
752
+ // otherPrimeInfos OtherPrimeInfos OPTIONAL
753
+ // }
754
+
755
+ return array(
756
+ 'privatekey' => $this->_convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients),
757
+ 'publickey' => $this->_convertPublicKey($n, $e),
758
+ 'partialkey' => false
759
+ );
760
+ }
761
+
762
+ /**
763
+ * Convert a private key to the appropriate format.
764
+ *
765
+ * @access private
766
+ * @see self::setPrivateKeyFormat()
767
+ * @param string $RSAPrivateKey
768
+ * @return string
769
+ */
770
+ function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
771
+ {
772
+ $signed = $this->privateKeyFormat != CRYPT_RSA_PRIVATE_FORMAT_XML;
773
+ $num_primes = count($primes);
774
+ $raw = array(
775
+ 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
776
+ 'modulus' => $n->toBytes($signed),
777
+ 'publicExponent' => $e->toBytes($signed),
778
+ 'privateExponent' => $d->toBytes($signed),
779
+ 'prime1' => $primes[1]->toBytes($signed),
780
+ 'prime2' => $primes[2]->toBytes($signed),
781
+ 'exponent1' => $exponents[1]->toBytes($signed),
782
+ 'exponent2' => $exponents[2]->toBytes($signed),
783
+ 'coefficient' => $coefficients[2]->toBytes($signed)
784
+ );
785
+
786
+ // if the format in question does not support multi-prime rsa and multi-prime rsa was used,
787
+ // call _convertPublicKey() instead.
788
+ switch ($this->privateKeyFormat) {
789
+ case CRYPT_RSA_PRIVATE_FORMAT_XML:
790
+ if ($num_primes != 2) {
791
+ return false;
792
+ }
793
+ return "<RSAKeyValue>\r\n" .
794
+ ' <Modulus>' . base64_encode($raw['modulus']) . "</Modulus>\r\n" .
795
+ ' <Exponent>' . base64_encode($raw['publicExponent']) . "</Exponent>\r\n" .
796
+ ' <P>' . base64_encode($raw['prime1']) . "</P>\r\n" .
797
+ ' <Q>' . base64_encode($raw['prime2']) . "</Q>\r\n" .
798
+ ' <DP>' . base64_encode($raw['exponent1']) . "</DP>\r\n" .
799
+ ' <DQ>' . base64_encode($raw['exponent2']) . "</DQ>\r\n" .
800
+ ' <InverseQ>' . base64_encode($raw['coefficient']) . "</InverseQ>\r\n" .
801
+ ' <D>' . base64_encode($raw['privateExponent']) . "</D>\r\n" .
802
+ '</RSAKeyValue>';
803
+ break;
804
+ case CRYPT_RSA_PRIVATE_FORMAT_PUTTY:
805
+ if ($num_primes != 2) {
806
+ return false;
807
+ }
808
+ $key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: ";
809
+ $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
810
+ $key.= $encryption;
811
+ $key.= "\r\nComment: " . $this->comment . "\r\n";
812
+ $public = pack(
813
+ 'Na*Na*Na*',
814
+ strlen('ssh-rsa'),
815
+ 'ssh-rsa',
816
+ strlen($raw['publicExponent']),
817
+ $raw['publicExponent'],
818
+ strlen($raw['modulus']),
819
+ $raw['modulus']
820
+ );
821
+ $source = pack(
822
+ 'Na*Na*Na*Na*',
823
+ strlen('ssh-rsa'),
824
+ 'ssh-rsa',
825
+ strlen($encryption),
826
+ $encryption,
827
+ strlen($this->comment),
828
+ $this->comment,
829
+ strlen($public),
830
+ $public
831
+ );
832
+ $public = base64_encode($public);
833
+ $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
834
+ $key.= chunk_split($public, 64);
835
+ $private = pack(
836
+ 'Na*Na*Na*Na*',
837
+ strlen($raw['privateExponent']),
838
+ $raw['privateExponent'],
839
+ strlen($raw['prime1']),
840
+ $raw['prime1'],
841
+ strlen($raw['prime2']),
842
+ $raw['prime2'],
843
+ strlen($raw['coefficient']),
844
+ $raw['coefficient']
845
+ );
846
+ if (empty($this->password) && !is_string($this->password)) {
847
+ $source.= pack('Na*', strlen($private), $private);
848
+ $hashkey = 'putty-private-key-file-mac-key';
849
+ } else {
850
+ $private.= crypt_random_string(16 - (strlen($private) & 15));
851
+ $source.= pack('Na*', strlen($private), $private);
852
+ if (!class_exists('Crypt_AES')) {
853
+ include_once 'Crypt/AES.php';
854
+ }
855
+ $sequence = 0;
856
+ $symkey = '';
857
+ while (strlen($symkey) < 32) {
858
+ $temp = pack('Na*', $sequence++, $this->password);
859
+ $symkey.= pack('H*', sha1($temp));
860
+ }
861
+ $symkey = substr($symkey, 0, 32);
862
+ $crypto = new Crypt_AES();
863
+
864
+ $crypto->setKey($symkey);
865
+ $crypto->disablePadding();
866
+ $private = $crypto->encrypt($private);
867
+ $hashkey = 'putty-private-key-file-mac-key' . $this->password;
868
+ }
869
+
870
+ $private = base64_encode($private);
871
+ $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n";
872
+ $key.= chunk_split($private, 64);
873
+ if (!class_exists('Crypt_Hash')) {
874
+ include_once 'Crypt/Hash.php';
875
+ }
876
+ $hash = new Crypt_Hash('sha1');
877
+ $hash->setKey(pack('H*', sha1($hashkey)));
878
+ $key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n";
879
+
880
+ return $key;
881
+ default: // eg. CRYPT_RSA_PRIVATE_FORMAT_PKCS1
882
+ $components = array();
883
+ foreach ($raw as $name => $value) {
884
+ $components[$name] = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value);
885
+ }
886
+
887
+ $RSAPrivateKey = implode('', $components);
888
+
889
+ if ($num_primes > 2) {
890
+ $OtherPrimeInfos = '';
891
+ for ($i = 3; $i <= $num_primes; $i++) {
892
+ // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
893
+ //
894
+ // OtherPrimeInfo ::= SEQUENCE {
895
+ // prime INTEGER, -- ri
896
+ // exponent INTEGER, -- di
897
+ // coefficient INTEGER -- ti
898
+ // }
899
+ $OtherPrimeInfo = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
900
+ $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
901
+ $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
902
+ $OtherPrimeInfos.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
903
+ }
904
+ $RSAPrivateKey.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
905
+ }
906
+
907
+ $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
908
+
909
+ if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) {
910
+ $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
911
+ $RSAPrivateKey = pack(
912
+ 'Ca*a*Ca*a*',
913
+ CRYPT_RSA_ASN1_INTEGER,
914
+ "\01\00",
915
+ $rsaOID,
916
+ 4,
917
+ $this->_encodeLength(strlen($RSAPrivateKey)),
918
+ $RSAPrivateKey
919
+ );
920
+ $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
921
+ if (!empty($this->password) || is_string($this->password)) {
922
+ $salt = crypt_random_string(8);
923
+ $iterationCount = 2048;
924
+
925
+ if (!class_exists('Crypt_DES')) {
926
+ include_once 'Crypt/DES.php';
927
+ }
928
+ $crypto = new Crypt_DES();
929
+ $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
930
+ $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
931
+
932
+ $parameters = pack(
933
+ 'Ca*a*Ca*N',
934
+ CRYPT_RSA_ASN1_OCTETSTRING,
935
+ $this->_encodeLength(strlen($salt)),
936
+ $salt,
937
+ CRYPT_RSA_ASN1_INTEGER,
938
+ $this->_encodeLength(4),
939
+ $iterationCount
940
+ );
941
+ $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
942
+
943
+ $encryptionAlgorithm = pack(
944
+ 'Ca*a*Ca*a*',
945
+ CRYPT_RSA_ASN1_OBJECT,
946
+ $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)),
947
+ $pbeWithMD5AndDES_CBC,
948
+ CRYPT_RSA_ASN1_SEQUENCE,
949
+ $this->_encodeLength(strlen($parameters)),
950
+ $parameters
951
+ );
952
+
953
+ $RSAPrivateKey = pack(
954
+ 'Ca*a*Ca*a*',
955
+ CRYPT_RSA_ASN1_SEQUENCE,
956
+ $this->_encodeLength(strlen($encryptionAlgorithm)),
957
+ $encryptionAlgorithm,
958
+ CRYPT_RSA_ASN1_OCTETSTRING,
959
+ $this->_encodeLength(strlen($RSAPrivateKey)),
960
+ $RSAPrivateKey
961
+ );
962
+
963
+ $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
964
+
965
+ $RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" .
966
+ chunk_split(base64_encode($RSAPrivateKey), 64) .
967
+ '-----END ENCRYPTED PRIVATE KEY-----';
968
+ } else {
969
+ $RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" .
970
+ chunk_split(base64_encode($RSAPrivateKey), 64) .
971
+ '-----END PRIVATE KEY-----';
972
+ }
973
+ return $RSAPrivateKey;
974
+ }
975
+
976
+ if (!empty($this->password) || is_string($this->password)) {
977
+ $iv = crypt_random_string(8);
978
+ $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
979
+ $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
980
+ if (!class_exists('Crypt_TripleDES')) {
981
+ include_once 'Crypt/TripleDES.php';
982
+ }
983
+ $des = new Crypt_TripleDES();
984
+ $des->setKey($symkey);
985
+ $des->setIV($iv);
986
+ $iv = strtoupper(bin2hex($iv));
987
+ $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
988
+ "Proc-Type: 4,ENCRYPTED\r\n" .
989
+ "DEK-Info: DES-EDE3-CBC,$iv\r\n" .
990
+ "\r\n" .
991
+ chunk_split(base64_encode($des->encrypt($RSAPrivateKey)), 64) .
992
+ '-----END RSA PRIVATE KEY-----';
993
+ } else {
994
+ $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
995
+ chunk_split(base64_encode($RSAPrivateKey), 64) .
996
+ '-----END RSA PRIVATE KEY-----';
997
+ }
998
+
999
+ return $RSAPrivateKey;
1000
+ }
1001
+ }
1002
+
1003
+ /**
1004
+ * Convert a public key to the appropriate format
1005
+ *
1006
+ * @access private
1007
+ * @see self::setPublicKeyFormat()
1008
+ * @param string $RSAPrivateKey
1009
+ * @return string
1010
+ */
1011
+ function _convertPublicKey($n, $e)
1012
+ {
1013
+ $signed = $this->publicKeyFormat != CRYPT_RSA_PUBLIC_FORMAT_XML;
1014
+
1015
+ $modulus = $n->toBytes($signed);
1016
+ $publicExponent = $e->toBytes($signed);
1017
+
1018
+ switch ($this->publicKeyFormat) {
1019
+ case CRYPT_RSA_PUBLIC_FORMAT_RAW:
1020
+ return array('e' => $e->copy(), 'n' => $n->copy());
1021
+ case CRYPT_RSA_PUBLIC_FORMAT_XML:
1022
+ return "<RSAKeyValue>\r\n" .
1023
+ ' <Modulus>' . base64_encode($modulus) . "</Modulus>\r\n" .
1024
+ ' <Exponent>' . base64_encode($publicExponent) . "</Exponent>\r\n" .
1025
+ '</RSAKeyValue>';
1026
+ break;
1027
+ case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
1028
+ // from <http://tools.ietf.org/html/rfc4253#page-15>:
1029
+ // string "ssh-rsa"
1030
+ // mpint e
1031
+ // mpint n
1032
+ $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
1033
+ $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $this->comment;
1034
+
1035
+ return $RSAPublicKey;
1036
+ default: // eg. CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW or CRYPT_RSA_PUBLIC_FORMAT_PKCS1
1037
+ // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
1038
+ // RSAPublicKey ::= SEQUENCE {
1039
+ // modulus INTEGER, -- n
1040
+ // publicExponent INTEGER -- e
1041
+ // }
1042
+ $components = array(
1043
+ 'modulus' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus),
1044
+ 'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
1045
+ );
1046
+
1047
+ $RSAPublicKey = pack(
1048
+ 'Ca*a*a*',
1049
+ CRYPT_RSA_ASN1_SEQUENCE,
1050
+ $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
1051
+ $components['modulus'],
1052
+ $components['publicExponent']
1053
+ );
1054
+
1055
+ if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) {
1056
+ $RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" .
1057
+ chunk_split(base64_encode($RSAPublicKey), 64) .
1058
+ '-----END RSA PUBLIC KEY-----';
1059
+ } else {
1060
+ // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
1061
+ $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
1062
+ $RSAPublicKey = chr(0) . $RSAPublicKey;
1063
+ $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
1064
+
1065
+ $RSAPublicKey = pack(
1066
+ 'Ca*a*',
1067
+ CRYPT_RSA_ASN1_SEQUENCE,
1068
+ $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)),
1069
+ $rsaOID . $RSAPublicKey
1070
+ );
1071
+
1072
+ $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
1073
+ chunk_split(base64_encode($RSAPublicKey), 64) .
1074
+ '-----END PUBLIC KEY-----';
1075
+ }
1076
+
1077
+ return $RSAPublicKey;
1078
+ }
1079
+ }
1080
+
1081
+ /**
1082
+ * Break a public or private key down into its constituant components
1083
+ *
1084
+ * @access private
1085
+ * @see self::_convertPublicKey()
1086
+ * @see self::_convertPrivateKey()
1087
+ * @param string $key
1088
+ * @param int $type
1089
+ * @return array
1090
+ */
1091
+ function _parseKey($key, $type)
1092
+ {
1093
+ if ($type != CRYPT_RSA_PUBLIC_FORMAT_RAW && !is_string($key)) {
1094
+ return false;
1095
+ }
1096
+
1097
+ switch ($type) {
1098
+ case CRYPT_RSA_PUBLIC_FORMAT_RAW:
1099
+ if (!is_array($key)) {
1100
+ return false;
1101
+ }
1102
+ $components = array();
1103
+ switch (true) {
1104
+ case isset($key['e']):
1105
+ $components['publicExponent'] = $key['e']->copy();
1106
+ break;
1107
+ case isset($key['exponent']):
1108
+ $components['publicExponent'] = $key['exponent']->copy();
1109
+ break;
1110
+ case isset($key['publicExponent']):
1111
+ $components['publicExponent'] = $key['publicExponent']->copy();
1112
+ break;
1113
+ case isset($key[0]):
1114
+ $components['publicExponent'] = $key[0]->copy();
1115
+ }
1116
+ switch (true) {
1117
+ case isset($key['n']):
1118
+ $components['modulus'] = $key['n']->copy();
1119
+ break;
1120
+ case isset($key['modulo']):
1121
+ $components['modulus'] = $key['modulo']->copy();
1122
+ break;
1123
+ case isset($key['modulus']):
1124
+ $components['modulus'] = $key['modulus']->copy();
1125
+ break;
1126
+ case isset($key[1]):
1127
+ $components['modulus'] = $key[1]->copy();
1128
+ }
1129
+ return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
1130
+ case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
1131
+ case CRYPT_RSA_PRIVATE_FORMAT_PKCS8:
1132
+ case CRYPT_RSA_PUBLIC_FORMAT_PKCS1:
1133
+ /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
1134
+ "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
1135
+ protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding
1136
+ two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here:
1137
+
1138
+ http://tools.ietf.org/html/rfc1421#section-4.6.1.1
1139
+ http://tools.ietf.org/html/rfc1421#section-4.6.1.3
1140
+
1141
+ DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
1142
+ DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
1143
+ function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
1144
+ own implementation. ie. the implementation *is* the standard and any bugs that may exist in that
1145
+ implementation are part of the standard, as well.
1146
+
1147
+ * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */
1148
+ if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
1149
+ $iv = pack('H*', trim($matches[2]));
1150
+ $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key
1151
+ $symkey.= pack('H*', md5($symkey . $this->password . substr($iv, 0, 8)));
1152
+ // remove the Proc-Type / DEK-Info sections as they're no longer needed
1153
+ $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key);
1154
+ $ciphertext = $this->_extractBER($key);
1155
+ if ($ciphertext === false) {
1156
+ $ciphertext = $key;
1157
+ }
1158
+ switch ($matches[1]) {
1159
+ case 'AES-256-CBC':
1160
+ if (!class_exists('Crypt_AES')) {
1161
+ include_once 'Crypt/AES.php';
1162
+ }
1163
+ $crypto = new Crypt_AES();
1164
+ break;
1165
+ case 'AES-128-CBC':
1166
+ if (!class_exists('Crypt_AES')) {
1167
+ include_once 'Crypt/AES.php';
1168
+ }
1169
+ $symkey = substr($symkey, 0, 16);
1170
+ $crypto = new Crypt_AES();
1171
+ break;
1172
+ case 'DES-EDE3-CFB':
1173
+ if (!class_exists('Crypt_TripleDES')) {
1174
+ include_once 'Crypt/TripleDES.php';
1175
+ }
1176
+ $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CFB);
1177
+ break;
1178
+ case 'DES-EDE3-CBC':
1179
+ if (!class_exists('Crypt_TripleDES')) {
1180
+ include_once 'Crypt/TripleDES.php';
1181
+ }
1182
+ $symkey = substr($symkey, 0, 24);
1183
+ $crypto = new Crypt_TripleDES();
1184
+ break;
1185
+ case 'DES-CBC':
1186
+ if (!class_exists('Crypt_DES')) {
1187
+ include_once 'Crypt/DES.php';
1188
+ }
1189
+ $crypto = new Crypt_DES();
1190
+ break;
1191
+ default:
1192
+ return false;
1193
+ }
1194
+ $crypto->setKey($symkey);
1195
+ $crypto->setIV($iv);
1196
+ $decoded = $crypto->decrypt($ciphertext);
1197
+ } else {
1198
+ $decoded = $this->_extractBER($key);
1199
+ }
1200
+
1201
+ if ($decoded !== false) {
1202
+ $key = $decoded;
1203
+ }
1204
+
1205
+ $components = array();
1206
+
1207
+ if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
1208
+ return false;
1209
+ }
1210
+ if ($this->_decodeLength($key) != strlen($key)) {
1211
+ return false;
1212
+ }
1213
+
1214
+ $tag = ord($this->_string_shift($key));
1215
+ /* intended for keys for which OpenSSL's asn1parse returns the following:
1216
+
1217
+ 0:d=0 hl=4 l= 631 cons: SEQUENCE
1218
+ 4:d=1 hl=2 l= 1 prim: INTEGER :00
1219
+ 7:d=1 hl=2 l= 13 cons: SEQUENCE
1220
+ 9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
1221
+ 20:d=2 hl=2 l= 0 prim: NULL
1222
+ 22:d=1 hl=4 l= 609 prim: OCTET STRING
1223
+
1224
+ ie. PKCS8 keys*/
1225
+
1226
+ if ($tag == CRYPT_RSA_ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") {
1227
+ $this->_string_shift($key, 3);
1228
+ $tag = CRYPT_RSA_ASN1_SEQUENCE;
1229
+ }
1230
+
1231
+ if ($tag == CRYPT_RSA_ASN1_SEQUENCE) {
1232
+ $temp = $this->_string_shift($key, $this->_decodeLength($key));
1233
+ if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_OBJECT) {
1234
+ return false;
1235
+ }
1236
+ $length = $this->_decodeLength($temp);
1237
+ switch ($this->_string_shift($temp, $length)) {
1238
+ case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
1239
+ break;
1240
+ case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
1241
+ /*
1242
+ PBEParameter ::= SEQUENCE {
1243
+ salt OCTET STRING (SIZE(8)),
1244
+ iterationCount INTEGER }
1245
+ */
1246
+ if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_SEQUENCE) {
1247
+ return false;
1248
+ }
1249
+ if ($this->_decodeLength($temp) != strlen($temp)) {
1250
+ return false;
1251
+ }
1252
+ $this->_string_shift($temp); // assume it's an octet string
1253
+ $salt = $this->_string_shift($temp, $this->_decodeLength($temp));
1254
+ if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_INTEGER) {
1255
+ return false;
1256
+ }
1257
+ $this->_decodeLength($temp);
1258
+ list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT));
1259
+ $this->_string_shift($key); // assume it's an octet string
1260
+ $length = $this->_decodeLength($key);
1261
+ if (strlen($key) != $length) {
1262
+ return false;
1263
+ }
1264
+
1265
+ if (!class_exists('Crypt_DES')) {
1266
+ include_once 'Crypt/DES.php';
1267
+ }
1268
+ $crypto = new Crypt_DES();
1269
+ $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
1270
+ $key = $crypto->decrypt($key);
1271
+ if ($key === false) {
1272
+ return false;
1273
+ }
1274
+ return $this->_parseKey($key, CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
1275
+ default:
1276
+ return false;
1277
+ }
1278
+ /* intended for keys for which OpenSSL's asn1parse returns the following:
1279
+
1280
+ 0:d=0 hl=4 l= 290 cons: SEQUENCE
1281
+ 4:d=1 hl=2 l= 13 cons: SEQUENCE
1282
+ 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
1283
+ 17:d=2 hl=2 l= 0 prim: NULL
1284
+ 19:d=1 hl=4 l= 271 prim: BIT STRING */
1285
+ $tag = ord($this->_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag
1286
+ $this->_decodeLength($key); // skip over the BIT STRING / OCTET STRING length
1287
+ // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of
1288
+ // unused bits in the final subsequent octet. The number shall be in the range zero to seven."
1289
+ // -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2)
1290
+ if ($tag == CRYPT_RSA_ASN1_BITSTRING) {
1291
+ $this->_string_shift($key);
1292
+ }
1293
+ if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
1294
+ return false;
1295
+ }
1296
+ if ($this->_decodeLength($key) != strlen($key)) {
1297
+ return false;
1298
+ }
1299
+ $tag = ord($this->_string_shift($key));
1300
+ }
1301
+ if ($tag != CRYPT_RSA_ASN1_INTEGER) {
1302
+ return false;
1303
+ }
1304
+
1305
+ $length = $this->_decodeLength($key);
1306
+ $temp = $this->_string_shift($key, $length);
1307
+ if (strlen($temp) != 1 || ord($temp) > 2) {
1308
+ $components['modulus'] = new Math_BigInteger($temp, 256);
1309
+ $this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER
1310
+ $length = $this->_decodeLength($key);
1311
+ $components[$type == CRYPT_RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1312
+
1313
+ return $components;
1314
+ }
1315
+ if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) {
1316
+ return false;
1317
+ }
1318
+ $length = $this->_decodeLength($key);
1319
+ $components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1320
+ $this->_string_shift($key);
1321
+ $length = $this->_decodeLength($key);
1322
+ $components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1323
+ $this->_string_shift($key);
1324
+ $length = $this->_decodeLength($key);
1325
+ $components['privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1326
+ $this->_string_shift($key);
1327
+ $length = $this->_decodeLength($key);
1328
+ $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), 256));
1329
+ $this->_string_shift($key);
1330
+ $length = $this->_decodeLength($key);
1331
+ $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1332
+ $this->_string_shift($key);
1333
+ $length = $this->_decodeLength($key);
1334
+ $components['exponents'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), 256));
1335
+ $this->_string_shift($key);
1336
+ $length = $this->_decodeLength($key);
1337
+ $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1338
+ $this->_string_shift($key);
1339
+ $length = $this->_decodeLength($key);
1340
+ $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), 256));
1341
+
1342
+ if (!empty($key)) {
1343
+ if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
1344
+ return false;
1345
+ }
1346
+ $this->_decodeLength($key);
1347
+ while (!empty($key)) {
1348
+ if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
1349
+ return false;
1350
+ }
1351
+ $this->_decodeLength($key);
1352
+ $key = substr($key, 1);
1353
+ $length = $this->_decodeLength($key);
1354
+ $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1355
+ $this->_string_shift($key);
1356
+ $length = $this->_decodeLength($key);
1357
+ $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1358
+ $this->_string_shift($key);
1359
+ $length = $this->_decodeLength($key);
1360
+ $components['coefficients'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
1361
+ }
1362
+ }
1363
+
1364
+ return $components;
1365
+ case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
1366
+ $parts = explode(' ', $key, 3);
1367
+
1368
+ $key = isset($parts[1]) ? base64_decode($parts[1]) : false;
1369
+ if ($key === false) {
1370
+ return false;
1371
+ }
1372
+
1373
+ $comment = isset($parts[2]) ? $parts[2] : false;
1374
+
1375
+ $cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa";
1376
+
1377
+ if (strlen($key) <= 4) {
1378
+ return false;
1379
+ }
1380
+ extract(unpack('Nlength', $this->_string_shift($key, 4)));
1381
+ $publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256);
1382
+ if (strlen($key) <= 4) {
1383
+ return false;
1384
+ }
1385
+ extract(unpack('Nlength', $this->_string_shift($key, 4)));
1386
+ $modulus = new Math_BigInteger($this->_string_shift($key, $length), -256);
1387
+
1388
+ if ($cleanup && strlen($key)) {
1389
+ if (strlen($key) <= 4) {
1390
+ return false;
1391
+ }
1392
+ extract(unpack('Nlength', $this->_string_shift($key, 4)));
1393
+ $realModulus = new Math_BigInteger($this->_string_shift($key, $length), -256);
1394
+ return strlen($key) ? false : array(
1395
+ 'modulus' => $realModulus,
1396
+ 'publicExponent' => $modulus,
1397
+ 'comment' => $comment
1398
+ );
1399
+ } else {
1400
+ return strlen($key) ? false : array(
1401
+ 'modulus' => $modulus,
1402
+ 'publicExponent' => $publicExponent,
1403
+ 'comment' => $comment
1404
+ );
1405
+ }
1406
+ // http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
1407
+ // http://en.wikipedia.org/wiki/XML_Signature
1408
+ case CRYPT_RSA_PRIVATE_FORMAT_XML:
1409
+ case CRYPT_RSA_PUBLIC_FORMAT_XML:
1410
+ $this->components = array();
1411
+
1412
+ $xml = xml_parser_create('UTF-8');
1413
+ xml_set_object($xml, $this);
1414
+ xml_set_element_handler($xml, '_start_element_handler', '_stop_element_handler');
1415
+ xml_set_character_data_handler($xml, '_data_handler');
1416
+ // add <xml></xml> to account for "dangling" tags like <BitStrength>...</BitStrength> that are sometimes added
1417
+ if (!xml_parse($xml, '<xml>' . $key . '</xml>')) {
1418
+ return false;
1419
+ }
1420
+
1421
+ return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false;
1422
+ // from PuTTY's SSHPUBK.C
1423
+ case CRYPT_RSA_PRIVATE_FORMAT_PUTTY:
1424
+ $components = array();
1425
+ $key = preg_split('#\r\n|\r|\n#', $key);
1426
+ $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
1427
+ if ($type != 'ssh-rsa') {
1428
+ return false;
1429
+ }
1430
+ $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
1431
+ $comment = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
1432
+
1433
+ $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3]));
1434
+ $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
1435
+ $public = substr($public, 11);
1436
+ extract(unpack('Nlength', $this->_string_shift($public, 4)));
1437
+ $components['publicExponent'] = new Math_BigInteger($this->_string_shift($public, $length), -256);
1438
+ extract(unpack('Nlength', $this->_string_shift($public, 4)));
1439
+ $components['modulus'] = new Math_BigInteger($this->_string_shift($public, $length), -256);
1440
+
1441
+ $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4]));
1442
+ $private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
1443
+
1444
+ switch ($encryption) {
1445
+ case 'aes256-cbc':
1446
+ if (!class_exists('Crypt_AES')) {
1447
+ include_once 'Crypt/AES.php';
1448
+ }
1449
+ $symkey = '';
1450
+ $sequence = 0;
1451
+ while (strlen($symkey) < 32) {
1452
+ $temp = pack('Na*', $sequence++, $this->password);
1453
+ $symkey.= pack('H*', sha1($temp));
1454
+ }
1455
+ $symkey = substr($symkey, 0, 32);
1456
+ $crypto = new Crypt_AES();
1457
+ }
1458
+
1459
+ if ($encryption != 'none') {
1460
+ $crypto->setKey($symkey);
1461
+ $crypto->disablePadding();
1462
+ $private = $crypto->decrypt($private);
1463
+ if ($private === false) {
1464
+ return false;
1465
+ }
1466
+ }
1467
+
1468
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
1469
+ if (strlen($private) < $length) {
1470
+ return false;
1471
+ }
1472
+ $components['privateExponent'] = new Math_BigInteger($this->_string_shift($private, $length), -256);
1473
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
1474
+ if (strlen($private) < $length) {
1475
+ return false;
1476
+ }
1477
+ $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($private, $length), -256));
1478
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
1479
+ if (strlen($private) < $length) {
1480
+ return false;
1481
+ }
1482
+ $components['primes'][] = new Math_BigInteger($this->_string_shift($private, $length), -256);
1483
+
1484
+ $temp = $components['primes'][1]->subtract($this->one);
1485
+ $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp));
1486
+ $temp = $components['primes'][2]->subtract($this->one);
1487
+ $components['exponents'][] = $components['publicExponent']->modInverse($temp);
1488
+
1489
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
1490
+ if (strlen($private) < $length) {
1491
+ return false;
1492
+ }
1493
+ $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($private, $length), -256));
1494
+
1495
+ return $components;
1496
+ }
1497
+ }
1498
+
1499
+ /**
1500
+ * Returns the key size
1501
+ *
1502
+ * More specifically, this returns the size of the modulo in bits.
1503
+ *
1504
+ * @access public
1505
+ * @return int
1506
+ */
1507
+ function getSize()
1508
+ {
1509
+ return !isset($this->modulus) ? 0 : strlen($this->modulus->toBits());
1510
+ }
1511
+
1512
+ /**
1513
+ * Start Element Handler
1514
+ *
1515
+ * Called by xml_set_element_handler()
1516
+ *
1517
+ * @access private
1518
+ * @param resource $parser
1519
+ * @param string $name
1520
+ * @param array $attribs
1521
+ */
1522
+ function _start_element_handler($parser, $name, $attribs)
1523
+ {
1524
+ //$name = strtoupper($name);
1525
+ switch ($name) {
1526
+ case 'MODULUS':
1527
+ $this->current = &$this->components['modulus'];
1528
+ break;
1529
+ case 'EXPONENT':
1530
+ $this->current = &$this->components['publicExponent'];
1531
+ break;
1532
+ case 'P':
1533
+ $this->current = &$this->components['primes'][1];
1534
+ break;
1535
+ case 'Q':
1536
+ $this->current = &$this->components['primes'][2];
1537
+ break;
1538
+ case 'DP':
1539
+ $this->current = &$this->components['exponents'][1];
1540
+ break;
1541
+ case 'DQ':
1542
+ $this->current = &$this->components['exponents'][2];
1543
+ break;
1544
+ case 'INVERSEQ':
1545
+ $this->current = &$this->components['coefficients'][2];
1546
+ break;
1547
+ case 'D':
1548
+ $this->current = &$this->components['privateExponent'];
1549
+ }
1550
+ $this->current = '';
1551
+ }
1552
+
1553
+ /**
1554
+ * Stop Element Handler
1555
+ *
1556
+ * Called by xml_set_element_handler()
1557
+ *
1558
+ * @access private
1559
+ * @param resource $parser
1560
+ * @param string $name
1561
+ */
1562
+ function _stop_element_handler($parser, $name)
1563
+ {
1564
+ if (isset($this->current)) {
1565
+ $this->current = new Math_BigInteger(base64_decode($this->current), 256);
1566
+ unset($this->current);
1567
+ }
1568
+ }
1569
+
1570
+ /**
1571
+ * Data Handler
1572
+ *
1573
+ * Called by xml_set_character_data_handler()
1574
+ *
1575
+ * @access private
1576
+ * @param resource $parser
1577
+ * @param string $data
1578
+ */
1579
+ function _data_handler($parser, $data)
1580
+ {
1581
+ if (!isset($this->current) || is_object($this->current)) {
1582
+ return;
1583
+ }
1584
+ $this->current.= trim($data);
1585
+ }
1586
+
1587
+ /**
1588
+ * Loads a public or private key
1589
+ *
1590
+ * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
1591
+ *
1592
+ * @access public
1593
+ * @param string $key
1594
+ * @param int $type optional
1595
+ */
1596
+ function loadKey($key, $type = false)
1597
+ {
1598
+ if (is_object($key) && strtolower(get_class($key)) == 'crypt_rsa') {
1599
+ $this->privateKeyFormat = $key->privateKeyFormat;
1600
+ $this->publicKeyFormat = $key->publicKeyFormat;
1601
+ $this->k = $key->k;
1602
+ $this->hLen = $key->hLen;
1603
+ $this->sLen = $key->sLen;
1604
+ $this->mgfHLen = $key->mgfHLen;
1605
+ $this->encryptionMode = $key->encryptionMode;
1606
+ $this->signatureMode = $key->signatureMode;
1607
+ $this->password = $key->password;
1608
+ $this->configFile = $key->configFile;
1609
+ $this->comment = $key->comment;
1610
+
1611
+ if (is_object($key->hash)) {
1612
+ $this->hash = new Crypt_Hash($key->hash->getHash());
1613
+ }
1614
+ if (is_object($key->mgfHash)) {
1615
+ $this->mgfHash = new Crypt_Hash($key->mgfHash->getHash());
1616
+ }
1617
+
1618
+ if (is_object($key->modulus)) {
1619
+ $this->modulus = $key->modulus->copy();
1620
+ }
1621
+ if (is_object($key->exponent)) {
1622
+ $this->exponent = $key->exponent->copy();
1623
+ }
1624
+ if (is_object($key->publicExponent)) {
1625
+ $this->publicExponent = $key->publicExponent->copy();
1626
+ }
1627
+
1628
+ $this->primes = array();
1629
+ $this->exponents = array();
1630
+ $this->coefficients = array();
1631
+
1632
+ foreach ($this->primes as $prime) {
1633
+ $this->primes[] = $prime->copy();
1634
+ }
1635
+ foreach ($this->exponents as $exponent) {
1636
+ $this->exponents[] = $exponent->copy();
1637
+ }
1638
+ foreach ($this->coefficients as $coefficient) {
1639
+ $this->coefficients[] = $coefficient->copy();
1640
+ }
1641
+
1642
+ return true;
1643
+ }
1644
+
1645
+ if ($type === false) {
1646
+ $types = array(
1647
+ CRYPT_RSA_PUBLIC_FORMAT_RAW,
1648
+ CRYPT_RSA_PRIVATE_FORMAT_PKCS1,
1649
+ CRYPT_RSA_PRIVATE_FORMAT_XML,
1650
+ CRYPT_RSA_PRIVATE_FORMAT_PUTTY,
1651
+ CRYPT_RSA_PUBLIC_FORMAT_OPENSSH
1652
+ );
1653
+ foreach ($types as $type) {
1654
+ $components = $this->_parseKey($key, $type);
1655
+ if ($components !== false) {
1656
+ break;
1657
+ }
1658
+ }
1659
+ } else {
1660
+ $components = $this->_parseKey($key, $type);
1661
+ }
1662
+
1663
+ if ($components === false) {
1664
+ return false;
1665
+ }
1666
+
1667
+ if (isset($components['comment']) && $components['comment'] !== false) {
1668
+ $this->comment = $components['comment'];
1669
+ }
1670
+ $this->modulus = $components['modulus'];
1671
+ $this->k = strlen($this->modulus->toBytes());
1672
+ $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
1673
+ if (isset($components['primes'])) {
1674
+ $this->primes = $components['primes'];
1675
+ $this->exponents = $components['exponents'];
1676
+ $this->coefficients = $components['coefficients'];
1677
+ $this->publicExponent = $components['publicExponent'];
1678
+ } else {
1679
+ $this->primes = array();
1680
+ $this->exponents = array();
1681
+ $this->coefficients = array();
1682
+ $this->publicExponent = false;
1683
+ }
1684
+
1685
+ switch ($type) {
1686
+ case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
1687
+ case CRYPT_RSA_PUBLIC_FORMAT_RAW:
1688
+ $this->setPublicKey();
1689
+ break;
1690
+ case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
1691
+ switch (true) {
1692
+ case strpos($key, '-BEGIN PUBLIC KEY-') !== false:
1693
+ case strpos($key, '-BEGIN RSA PUBLIC KEY-') !== false:
1694
+ $this->setPublicKey();
1695
+ }
1696
+ }
1697
+
1698
+ return true;
1699
+ }
1700
+
1701
+ /**
1702
+ * Sets the password
1703
+ *
1704
+ * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false.
1705
+ * Or rather, pass in $password such that empty($password) && !is_string($password) is true.
1706
+ *
1707
+ * @see self::createKey()
1708
+ * @see self::loadKey()
1709
+ * @access public
1710
+ * @param string $password
1711
+ */
1712
+ function setPassword($password = false)
1713
+ {
1714
+ $this->password = $password;
1715
+ }
1716
+
1717
+ /**
1718
+ * Defines the public key
1719
+ *
1720
+ * Some private key formats define the public exponent and some don't. Those that don't define it are problematic when
1721
+ * used in certain contexts. For example, in SSH-2, RSA authentication works by sending the public key along with a
1722
+ * message signed by the private key to the server. The SSH-2 server looks the public key up in an index of public keys
1723
+ * and if it's present then proceeds to verify the signature. Problem is, if your private key doesn't include the public
1724
+ * exponent this won't work unless you manually add the public exponent. phpseclib tries to guess if the key being used
1725
+ * is the public key but in the event that it guesses incorrectly you might still want to explicitly set the key as being
1726
+ * public.
1727
+ *
1728
+ * Do note that when a new key is loaded the index will be cleared.
1729
+ *
1730
+ * Returns true on success, false on failure
1731
+ *
1732
+ * @see self::getPublicKey()
1733
+ * @access public
1734
+ * @param string $key optional
1735
+ * @param int $type optional
1736
+ * @return bool
1737
+ */
1738
+ function setPublicKey($key = false, $type = false)
1739
+ {
1740
+ // if a public key has already been loaded return false
1741
+ if (!empty($this->publicExponent)) {
1742
+ return false;
1743
+ }
1744
+
1745
+ if ($key === false && !empty($this->modulus)) {
1746
+ $this->publicExponent = $this->exponent;
1747
+ return true;
1748
+ }
1749
+
1750
+ if ($type === false) {
1751
+ $types = array(
1752
+ CRYPT_RSA_PUBLIC_FORMAT_RAW,
1753
+ CRYPT_RSA_PUBLIC_FORMAT_PKCS1,
1754
+ CRYPT_RSA_PUBLIC_FORMAT_XML,
1755
+ CRYPT_RSA_PUBLIC_FORMAT_OPENSSH
1756
+ );
1757
+ foreach ($types as $type) {
1758
+ $components = $this->_parseKey($key, $type);
1759
+ if ($components !== false) {
1760
+ break;
1761
+ }
1762
+ }
1763
+ } else {
1764
+ $components = $this->_parseKey($key, $type);
1765
+ }
1766
+
1767
+ if ($components === false) {
1768
+ return false;
1769
+ }
1770
+
1771
+ if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) {
1772
+ $this->modulus = $components['modulus'];
1773
+ $this->exponent = $this->publicExponent = $components['publicExponent'];
1774
+ return true;
1775
+ }
1776
+
1777
+ $this->publicExponent = $components['publicExponent'];
1778
+
1779
+ return true;
1780
+ }
1781
+
1782
+ /**
1783
+ * Defines the private key
1784
+ *
1785
+ * If phpseclib guessed a private key was a public key and loaded it as such it might be desirable to force
1786
+ * phpseclib to treat the key as a private key. This function will do that.
1787
+ *
1788
+ * Do note that when a new key is loaded the index will be cleared.
1789
+ *
1790
+ * Returns true on success, false on failure
1791
+ *
1792
+ * @see self::getPublicKey()
1793
+ * @access public
1794
+ * @param string $key optional
1795
+ * @param int $type optional
1796
+ * @return bool
1797
+ */
1798
+ function setPrivateKey($key = false, $type = false)
1799
+ {
1800
+ if ($key === false && !empty($this->publicExponent)) {
1801
+ $this->publicExponent = false;
1802
+ return true;
1803
+ }
1804
+
1805
+ $rsa = new Crypt_RSA();
1806
+ if (!$rsa->loadKey($key, $type)) {
1807
+ return false;
1808
+ }
1809
+ $rsa->publicExponent = false;
1810
+
1811
+ // don't overwrite the old key if the new key is invalid
1812
+ $this->loadKey($rsa);
1813
+ return true;
1814
+ }
1815
+
1816
+ /**
1817
+ * Returns the public key
1818
+ *
1819
+ * The public key is only returned under two circumstances - if the private key had the public key embedded within it
1820
+ * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this
1821
+ * function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
1822
+ *
1823
+ * @see self::getPublicKey()
1824
+ * @access public
1825
+ * @param string $key
1826
+ * @param int $type optional
1827
+ */
1828
+ function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
1829
+ {
1830
+ if (empty($this->modulus) || empty($this->publicExponent)) {
1831
+ return false;
1832
+ }
1833
+
1834
+ $oldFormat = $this->publicKeyFormat;
1835
+ $this->publicKeyFormat = $type;
1836
+ $temp = $this->_convertPublicKey($this->modulus, $this->publicExponent);
1837
+ $this->publicKeyFormat = $oldFormat;
1838
+ return $temp;
1839
+ }
1840
+
1841
+ /**
1842
+ * Returns the public key's fingerprint
1843
+ *
1844
+ * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is
1845
+ * no public key currently loaded, false is returned.
1846
+ * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
1847
+ *
1848
+ * @access public
1849
+ * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
1850
+ * for invalid values.
1851
+ * @return mixed
1852
+ */
1853
+ function getPublicKeyFingerprint($algorithm = 'md5')
1854
+ {
1855
+ if (empty($this->modulus) || empty($this->publicExponent)) {
1856
+ return false;
1857
+ }
1858
+
1859
+ $modulus = $this->modulus->toBytes(true);
1860
+ $publicExponent = $this->publicExponent->toBytes(true);
1861
+
1862
+ $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
1863
+
1864
+ switch ($algorithm) {
1865
+ case 'sha256':
1866
+ $hash = new Crypt_Hash('sha256');
1867
+ $base = base64_encode($hash->hash($RSAPublicKey));
1868
+ return substr($base, 0, strlen($base) - 1);
1869
+ case 'md5':
1870
+ return substr(chunk_split(md5($RSAPublicKey), 2, ':'), 0, -1);
1871
+ default:
1872
+ return false;
1873
+ }
1874
+ }
1875
+
1876
+ /**
1877
+ * Returns the private key
1878
+ *
1879
+ * The private key is only returned if the currently loaded key contains the constituent prime numbers.
1880
+ *
1881
+ * @see self::getPublicKey()
1882
+ * @access public
1883
+ * @param string $key
1884
+ * @param int $type optional
1885
+ * @return mixed
1886
+ */
1887
+ function getPrivateKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
1888
+ {
1889
+ if (empty($this->primes)) {
1890
+ return false;
1891
+ }
1892
+
1893
+ $oldFormat = $this->privateKeyFormat;
1894
+ $this->privateKeyFormat = $type;
1895
+ $temp = $this->_convertPrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients);
1896
+ $this->privateKeyFormat = $oldFormat;
1897
+ return $temp;
1898
+ }
1899
+
1900
+ /**
1901
+ * Returns a minimalistic private key
1902
+ *
1903
+ * Returns the private key without the prime number constituants. Structurally identical to a public key that
1904
+ * hasn't been set as the public key
1905
+ *
1906
+ * @see self::getPrivateKey()
1907
+ * @access private
1908
+ * @param string $key
1909
+ * @param int $type optional
1910
+ */
1911
+ function _getPrivatePublicKey($mode = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
1912
+ {
1913
+ if (empty($this->modulus) || empty($this->exponent)) {
1914
+ return false;
1915
+ }
1916
+
1917
+ $oldFormat = $this->publicKeyFormat;
1918
+ $this->publicKeyFormat = $mode;
1919
+ $temp = $this->_convertPublicKey($this->modulus, $this->exponent);
1920
+ $this->publicKeyFormat = $oldFormat;
1921
+ return $temp;
1922
+ }
1923
+
1924
+ /**
1925
+ * __toString() magic method
1926
+ *
1927
+ * @access public
1928
+ * @return string
1929
+ */
1930
+ function __toString()
1931
+ {
1932
+ $key = $this->getPrivateKey($this->privateKeyFormat);
1933
+ if ($key !== false) {
1934
+ return $key;
1935
+ }
1936
+ $key = $this->_getPrivatePublicKey($this->publicKeyFormat);
1937
+ return $key !== false ? $key : '';
1938
+ }
1939
+
1940
+ /**
1941
+ * __clone() magic method
1942
+ *
1943
+ * @access public
1944
+ * @return Crypt_RSA
1945
+ */
1946
+ function __clone()
1947
+ {
1948
+ $key = new Crypt_RSA();
1949
+ $key->loadKey($this);
1950
+ return $key;
1951
+ }
1952
+
1953
+ /**
1954
+ * Generates the smallest and largest numbers requiring $bits bits
1955
+ *
1956
+ * @access private
1957
+ * @param int $bits
1958
+ * @return array
1959
+ */
1960
+ function _generateMinMax($bits)
1961
+ {
1962
+ $bytes = $bits >> 3;
1963
+ $min = str_repeat(chr(0), $bytes);
1964
+ $max = str_repeat(chr(0xFF), $bytes);
1965
+ $msb = $bits & 7;
1966
+ if ($msb) {
1967
+ $min = chr(1 << ($msb - 1)) . $min;
1968
+ $max = chr((1 << $msb) - 1) . $max;
1969
+ } else {
1970
+ $min[0] = chr(0x80);
1971
+ }
1972
+
1973
+ return array(
1974
+ 'min' => new Math_BigInteger($min, 256),
1975
+ 'max' => new Math_BigInteger($max, 256)
1976
+ );
1977
+ }
1978
+
1979
+ /**
1980
+ * DER-decode the length
1981
+ *
1982
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
1983
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
1984
+ *
1985
+ * @access private
1986
+ * @param string $string
1987
+ * @return int
1988
+ */
1989
+ function _decodeLength(&$string)
1990
+ {
1991
+ $length = ord($this->_string_shift($string));
1992
+ if ($length & 0x80) { // definite length, long form
1993
+ $length&= 0x7F;
1994
+ $temp = $this->_string_shift($string, $length);
1995
+ list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
1996
+ }
1997
+ return $length;
1998
+ }
1999
+
2000
+ /**
2001
+ * DER-encode the length
2002
+ *
2003
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
2004
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
2005
+ *
2006
+ * @access private
2007
+ * @param int $length
2008
+ * @return string
2009
+ */
2010
+ function _encodeLength($length)
2011
+ {
2012
+ if ($length <= 0x7F) {
2013
+ return chr($length);
2014
+ }
2015
+
2016
+ $temp = ltrim(pack('N', $length), chr(0));
2017
+ return pack('Ca*', 0x80 | strlen($temp), $temp);
2018
+ }
2019
+
2020
+ /**
2021
+ * String Shift
2022
+ *
2023
+ * Inspired by array_shift
2024
+ *
2025
+ * @param string $string
2026
+ * @param int $index
2027
+ * @return string
2028
+ * @access private
2029
+ */
2030
+ function _string_shift(&$string, $index = 1)
2031
+ {
2032
+ $substr = substr($string, 0, $index);
2033
+ $string = substr($string, $index);
2034
+ return $substr;
2035
+ }
2036
+
2037
+ /**
2038
+ * Determines the private key format
2039
+ *
2040
+ * @see self::createKey()
2041
+ * @access public
2042
+ * @param int $format
2043
+ */
2044
+ function setPrivateKeyFormat($format)
2045
+ {
2046
+ $this->privateKeyFormat = $format;
2047
+ }
2048
+
2049
+ /**
2050
+ * Determines the public key format
2051
+ *
2052
+ * @see self::createKey()
2053
+ * @access public
2054
+ * @param int $format
2055
+ */
2056
+ function setPublicKeyFormat($format)
2057
+ {
2058
+ $this->publicKeyFormat = $format;
2059
+ }
2060
+
2061
+ /**
2062
+ * Determines which hashing function should be used
2063
+ *
2064
+ * Used with signature production / verification and (if the encryption mode is CRYPT_RSA_ENCRYPTION_OAEP) encryption and
2065
+ * decryption. If $hash isn't supported, sha1 is used.
2066
+ *
2067
+ * @access public
2068
+ * @param string $hash
2069
+ */
2070
+ function setHash($hash)
2071
+ {
2072
+ // Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
2073
+ switch ($hash) {
2074
+ case 'md2':
2075
+ case 'md5':
2076
+ case 'sha1':
2077
+ case 'sha256':
2078
+ case 'sha384':
2079
+ case 'sha512':
2080
+ $this->hash = new Crypt_Hash($hash);
2081
+ $this->hashName = $hash;
2082
+ break;
2083
+ default:
2084
+ $this->hash = new Crypt_Hash('sha1');
2085
+ $this->hashName = 'sha1';
2086
+ }
2087
+ $this->hLen = $this->hash->getLength();
2088
+ }
2089
+
2090
+ /**
2091
+ * Determines which hashing function should be used for the mask generation function
2092
+ *
2093
+ * The mask generation function is used by CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_SIGNATURE_PSS and although it's
2094
+ * best if Hash and MGFHash are set to the same thing this is not a requirement.
2095
+ *
2096
+ * @access public
2097
+ * @param string $hash
2098
+ */
2099
+ function setMGFHash($hash)
2100
+ {
2101
+ // Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
2102
+ switch ($hash) {
2103
+ case 'md2':
2104
+ case 'md5':
2105
+ case 'sha1':
2106
+ case 'sha256':
2107
+ case 'sha384':
2108
+ case 'sha512':
2109
+ $this->mgfHash = new Crypt_Hash($hash);
2110
+ break;
2111
+ default:
2112
+ $this->mgfHash = new Crypt_Hash('sha1');
2113
+ }
2114
+ $this->mgfHLen = $this->mgfHash->getLength();
2115
+ }
2116
+
2117
+ /**
2118
+ * Determines the salt length
2119
+ *
2120
+ * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}:
2121
+ *
2122
+ * Typical salt lengths in octets are hLen (the length of the output
2123
+ * of the hash function Hash) and 0.
2124
+ *
2125
+ * @access public
2126
+ * @param int $format
2127
+ */
2128
+ function setSaltLength($sLen)
2129
+ {
2130
+ $this->sLen = $sLen;
2131
+ }
2132
+
2133
+ /**
2134
+ * Integer-to-Octet-String primitive
2135
+ *
2136
+ * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
2137
+ *
2138
+ * @access private
2139
+ * @param Math_BigInteger $x
2140
+ * @param int $xLen
2141
+ * @return string
2142
+ */
2143
+ function _i2osp($x, $xLen)
2144
+ {
2145
+ $x = $x->toBytes();
2146
+ if (strlen($x) > $xLen) {
2147
+ user_error('Integer too large');
2148
+ return false;
2149
+ }
2150
+ return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
2151
+ }
2152
+
2153
+ /**
2154
+ * Octet-String-to-Integer primitive
2155
+ *
2156
+ * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
2157
+ *
2158
+ * @access private
2159
+ * @param string $x
2160
+ * @return Math_BigInteger
2161
+ */
2162
+ function _os2ip($x)
2163
+ {
2164
+ return new Math_BigInteger($x, 256);
2165
+ }
2166
+
2167
+ /**
2168
+ * Exponentiate with or without Chinese Remainder Theorem
2169
+ *
2170
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.2}.
2171
+ *
2172
+ * @access private
2173
+ * @param Math_BigInteger $x
2174
+ * @return Math_BigInteger
2175
+ */
2176
+ function _exponentiate($x)
2177
+ {
2178
+ switch (true) {
2179
+ case empty($this->primes):
2180
+ case $this->primes[1]->equals($this->zero):
2181
+ case empty($this->coefficients):
2182
+ case $this->coefficients[2]->equals($this->zero):
2183
+ case empty($this->exponents):
2184
+ case $this->exponents[1]->equals($this->zero):
2185
+ return $x->modPow($this->exponent, $this->modulus);
2186
+ }
2187
+
2188
+ $num_primes = count($this->primes);
2189
+
2190
+ if (defined('CRYPT_RSA_DISABLE_BLINDING')) {
2191
+ $m_i = array(
2192
+ 1 => $x->modPow($this->exponents[1], $this->primes[1]),
2193
+ 2 => $x->modPow($this->exponents[2], $this->primes[2])
2194
+ );
2195
+ $h = $m_i[1]->subtract($m_i[2]);
2196
+ $h = $h->multiply($this->coefficients[2]);
2197
+ list(, $h) = $h->divide($this->primes[1]);
2198
+ $m = $m_i[2]->add($h->multiply($this->primes[2]));
2199
+
2200
+ $r = $this->primes[1];
2201
+ for ($i = 3; $i <= $num_primes; $i++) {
2202
+ $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]);
2203
+
2204
+ $r = $r->multiply($this->primes[$i - 1]);
2205
+
2206
+ $h = $m_i->subtract($m);
2207
+ $h = $h->multiply($this->coefficients[$i]);
2208
+ list(, $h) = $h->divide($this->primes[$i]);
2209
+
2210
+ $m = $m->add($r->multiply($h));
2211
+ }
2212
+ } else {
2213
+ $smallest = $this->primes[1];
2214
+ for ($i = 2; $i <= $num_primes; $i++) {
2215
+ if ($smallest->compare($this->primes[$i]) > 0) {
2216
+ $smallest = $this->primes[$i];
2217
+ }
2218
+ }
2219
+
2220
+ $one = new Math_BigInteger(1);
2221
+
2222
+ $r = $one->random($one, $smallest->subtract($one));
2223
+
2224
+ $m_i = array(
2225
+ 1 => $this->_blind($x, $r, 1),
2226
+ 2 => $this->_blind($x, $r, 2)
2227
+ );
2228
+ $h = $m_i[1]->subtract($m_i[2]);
2229
+ $h = $h->multiply($this->coefficients[2]);
2230
+ list(, $h) = $h->divide($this->primes[1]);
2231
+ $m = $m_i[2]->add($h->multiply($this->primes[2]));
2232
+
2233
+ $r = $this->primes[1];
2234
+ for ($i = 3; $i <= $num_primes; $i++) {
2235
+ $m_i = $this->_blind($x, $r, $i);
2236
+
2237
+ $r = $r->multiply($this->primes[$i - 1]);
2238
+
2239
+ $h = $m_i->subtract($m);
2240
+ $h = $h->multiply($this->coefficients[$i]);
2241
+ list(, $h) = $h->divide($this->primes[$i]);
2242
+
2243
+ $m = $m->add($r->multiply($h));
2244
+ }
2245
+ }
2246
+
2247
+ return $m;
2248
+ }
2249
+
2250
+ /**
2251
+ * Performs RSA Blinding
2252
+ *
2253
+ * Protects against timing attacks by employing RSA Blinding.
2254
+ * Returns $x->modPow($this->exponents[$i], $this->primes[$i])
2255
+ *
2256
+ * @access private
2257
+ * @param Math_BigInteger $x
2258
+ * @param Math_BigInteger $r
2259
+ * @param int $i
2260
+ * @return Math_BigInteger
2261
+ */
2262
+ function _blind($x, $r, $i)
2263
+ {
2264
+ $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i]));
2265
+ $x = $x->modPow($this->exponents[$i], $this->primes[$i]);
2266
+
2267
+ $r = $r->modInverse($this->primes[$i]);
2268
+ $x = $x->multiply($r);
2269
+ list(, $x) = $x->divide($this->primes[$i]);
2270
+
2271
+ return $x;
2272
+ }
2273
+
2274
+ /**
2275
+ * Performs blinded RSA equality testing
2276
+ *
2277
+ * Protects against a particular type of timing attack described.
2278
+ *
2279
+ * See {@link http://codahale.com/a-lesson-in-timing-attacks/ A Lesson In Timing Attacks (or, Don't use MessageDigest.isEquals)}
2280
+ *
2281
+ * Thanks for the heads up singpolyma!
2282
+ *
2283
+ * @access private
2284
+ * @param string $x
2285
+ * @param string $y
2286
+ * @return bool
2287
+ */
2288
+ function _equals($x, $y)
2289
+ {
2290
+ if (strlen($x) != strlen($y)) {
2291
+ return false;
2292
+ }
2293
+
2294
+ $result = 0;
2295
+ for ($i = 0; $i < strlen($x); $i++) {
2296
+ $result |= ord($x[$i]) ^ ord($y[$i]);
2297
+ }
2298
+
2299
+ return $result == 0;
2300
+ }
2301
+
2302
+ /**
2303
+ * RSAEP
2304
+ *
2305
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}.
2306
+ *
2307
+ * @access private
2308
+ * @param Math_BigInteger $m
2309
+ * @return Math_BigInteger
2310
+ */
2311
+ function _rsaep($m)
2312
+ {
2313
+ if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
2314
+ user_error('Message representative out of range');
2315
+ return false;
2316
+ }
2317
+ return $this->_exponentiate($m);
2318
+ }
2319
+
2320
+ /**
2321
+ * RSADP
2322
+ *
2323
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}.
2324
+ *
2325
+ * @access private
2326
+ * @param Math_BigInteger $c
2327
+ * @return Math_BigInteger
2328
+ */
2329
+ function _rsadp($c)
2330
+ {
2331
+ if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) {
2332
+ user_error('Ciphertext representative out of range');
2333
+ return false;
2334
+ }
2335
+ return $this->_exponentiate($c);
2336
+ }
2337
+
2338
+ /**
2339
+ * RSASP1
2340
+ *
2341
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}.
2342
+ *
2343
+ * @access private
2344
+ * @param Math_BigInteger $m
2345
+ * @return Math_BigInteger
2346
+ */
2347
+ function _rsasp1($m)
2348
+ {
2349
+ if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
2350
+ user_error('Message representative out of range');
2351
+ return false;
2352
+ }
2353
+ return $this->_exponentiate($m);
2354
+ }
2355
+
2356
+ /**
2357
+ * RSAVP1
2358
+ *
2359
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
2360
+ *
2361
+ * @access private
2362
+ * @param Math_BigInteger $s
2363
+ * @return Math_BigInteger
2364
+ */
2365
+ function _rsavp1($s)
2366
+ {
2367
+ if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) {
2368
+ user_error('Signature representative out of range');
2369
+ return false;
2370
+ }
2371
+ return $this->_exponentiate($s);
2372
+ }
2373
+
2374
+ /**
2375
+ * MGF1
2376
+ *
2377
+ * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
2378
+ *
2379
+ * @access private
2380
+ * @param string $mgfSeed
2381
+ * @param int $mgfLen
2382
+ * @return string
2383
+ */
2384
+ function _mgf1($mgfSeed, $maskLen)
2385
+ {
2386
+ // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
2387
+
2388
+ $t = '';
2389
+ $count = ceil($maskLen / $this->mgfHLen);
2390
+ for ($i = 0; $i < $count; $i++) {
2391
+ $c = pack('N', $i);
2392
+ $t.= $this->mgfHash->hash($mgfSeed . $c);
2393
+ }
2394
+
2395
+ return substr($t, 0, $maskLen);
2396
+ }
2397
+
2398
+ /**
2399
+ * RSAES-OAEP-ENCRYPT
2400
+ *
2401
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and
2402
+ * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
2403
+ *
2404
+ * @access private
2405
+ * @param string $m
2406
+ * @param string $l
2407
+ * @return string
2408
+ */
2409
+ function _rsaes_oaep_encrypt($m, $l = '')
2410
+ {
2411
+ $mLen = strlen($m);
2412
+
2413
+ // Length checking
2414
+
2415
+ // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
2416
+ // be output.
2417
+
2418
+ if ($mLen > $this->k - 2 * $this->hLen - 2) {
2419
+ user_error('Message too long');
2420
+ return false;
2421
+ }
2422
+
2423
+ // EME-OAEP encoding
2424
+
2425
+ $lHash = $this->hash->hash($l);
2426
+ $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2);
2427
+ $db = $lHash . $ps . chr(1) . $m;
2428
+ $seed = crypt_random_string($this->hLen);
2429
+ $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1);
2430
+ $maskedDB = $db ^ $dbMask;
2431
+ $seedMask = $this->_mgf1($maskedDB, $this->hLen);
2432
+ $maskedSeed = $seed ^ $seedMask;
2433
+ $em = chr(0) . $maskedSeed . $maskedDB;
2434
+
2435
+ // RSA encryption
2436
+
2437
+ $m = $this->_os2ip($em);
2438
+ $c = $this->_rsaep($m);
2439
+ $c = $this->_i2osp($c, $this->k);
2440
+
2441
+ // Output the ciphertext C
2442
+
2443
+ return $c;
2444
+ }
2445
+
2446
+ /**
2447
+ * RSAES-OAEP-DECRYPT
2448
+ *
2449
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error
2450
+ * messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2:
2451
+ *
2452
+ * Note. Care must be taken to ensure that an opponent cannot
2453
+ * distinguish the different error conditions in Step 3.g, whether by
2454
+ * error message or timing, or, more generally, learn partial
2455
+ * information about the encoded message EM. Otherwise an opponent may
2456
+ * be able to obtain useful information about the decryption of the
2457
+ * ciphertext C, leading to a chosen-ciphertext attack such as the one
2458
+ * observed by Manger [36].
2459
+ *
2460
+ * As for $l... to quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}:
2461
+ *
2462
+ * Both the encryption and the decryption operations of RSAES-OAEP take
2463
+ * the value of a label L as input. In this version of PKCS #1, L is
2464
+ * the empty string; other uses of the label are outside the scope of
2465
+ * this document.
2466
+ *
2467
+ * @access private
2468
+ * @param string $c
2469
+ * @param string $l
2470
+ * @return string
2471
+ */
2472
+ function _rsaes_oaep_decrypt($c, $l = '')
2473
+ {
2474
+ // Length checking
2475
+
2476
+ // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
2477
+ // be output.
2478
+
2479
+ if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) {
2480
+ user_error('Decryption error');
2481
+ return false;
2482
+ }
2483
+
2484
+ // RSA decryption
2485
+
2486
+ $c = $this->_os2ip($c);
2487
+ $m = $this->_rsadp($c);
2488
+ if ($m === false) {
2489
+ user_error('Decryption error');
2490
+ return false;
2491
+ }
2492
+ $em = $this->_i2osp($m, $this->k);
2493
+
2494
+ // EME-OAEP decoding
2495
+
2496
+ $lHash = $this->hash->hash($l);
2497
+ $y = ord($em[0]);
2498
+ $maskedSeed = substr($em, 1, $this->hLen);
2499
+ $maskedDB = substr($em, $this->hLen + 1);
2500
+ $seedMask = $this->_mgf1($maskedDB, $this->hLen);
2501
+ $seed = $maskedSeed ^ $seedMask;
2502
+ $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1);
2503
+ $db = $maskedDB ^ $dbMask;
2504
+ $lHash2 = substr($db, 0, $this->hLen);
2505
+ $m = substr($db, $this->hLen);
2506
+ if ($lHash != $lHash2) {
2507
+ user_error('Decryption error');
2508
+ return false;
2509
+ }
2510
+ $m = ltrim($m, chr(0));
2511
+ if (ord($m[0]) != 1) {
2512
+ user_error('Decryption error');
2513
+ return false;
2514
+ }
2515
+
2516
+ // Output the message M
2517
+
2518
+ return substr($m, 1);
2519
+ }
2520
+
2521
+ /**
2522
+ * Raw Encryption / Decryption
2523
+ *
2524
+ * Doesn't use padding and is not recommended.
2525
+ *
2526
+ * @access private
2527
+ * @param string $m
2528
+ * @return string
2529
+ */
2530
+ function _raw_encrypt($m)
2531
+ {
2532
+ $temp = $this->_os2ip($m);
2533
+ $temp = $this->_rsaep($temp);
2534
+ return $this->_i2osp($temp, $this->k);
2535
+ }
2536
+
2537
+ /**
2538
+ * RSAES-PKCS1-V1_5-ENCRYPT
2539
+ *
2540
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
2541
+ *
2542
+ * @access private
2543
+ * @param string $m
2544
+ * @return string
2545
+ */
2546
+ function _rsaes_pkcs1_v1_5_encrypt($m)
2547
+ {
2548
+ $mLen = strlen($m);
2549
+
2550
+ // Length checking
2551
+
2552
+ if ($mLen > $this->k - 11) {
2553
+ user_error('Message too long');
2554
+ return false;
2555
+ }
2556
+
2557
+ // EME-PKCS1-v1_5 encoding
2558
+
2559
+ $psLen = $this->k - $mLen - 3;
2560
+ $ps = '';
2561
+ while (strlen($ps) != $psLen) {
2562
+ $temp = crypt_random_string($psLen - strlen($ps));
2563
+ $temp = str_replace("\x00", '', $temp);
2564
+ $ps.= $temp;
2565
+ }
2566
+ $type = 2;
2567
+ // see the comments of _rsaes_pkcs1_v1_5_decrypt() to understand why this is being done
2568
+ if (defined('CRYPT_RSA_PKCS15_COMPAT') && (!isset($this->publicExponent) || $this->exponent !== $this->publicExponent)) {
2569
+ $type = 1;
2570
+ // "The padding string PS shall consist of k-3-||D|| octets. ... for block type 01, they shall have value FF"
2571
+ $ps = str_repeat("\xFF", $psLen);
2572
+ }
2573
+ $em = chr(0) . chr($type) . $ps . chr(0) . $m;
2574
+
2575
+ // RSA encryption
2576
+ $m = $this->_os2ip($em);
2577
+ $c = $this->_rsaep($m);
2578
+ $c = $this->_i2osp($c, $this->k);
2579
+
2580
+ // Output the ciphertext C
2581
+
2582
+ return $c;
2583
+ }
2584
+
2585
+ /**
2586
+ * RSAES-PKCS1-V1_5-DECRYPT
2587
+ *
2588
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}.
2589
+ *
2590
+ * For compatibility purposes, this function departs slightly from the description given in RFC3447.
2591
+ * The reason being that RFC2313#section-8.1 (PKCS#1 v1.5) states that ciphertext's encrypted by the
2592
+ * private key should have the second byte set to either 0 or 1 and that ciphertext's encrypted by the
2593
+ * public key should have the second byte set to 2. In RFC3447 (PKCS#1 v2.1), the second byte is supposed
2594
+ * to be 2 regardless of which key is used. For compatibility purposes, we'll just check to make sure the
2595
+ * second byte is 2 or less. If it is, we'll accept the decrypted string as valid.
2596
+ *
2597
+ * As a consequence of this, a private key encrypted ciphertext produced with Crypt_RSA may not decrypt
2598
+ * with a strictly PKCS#1 v1.5 compliant RSA implementation. Public key encrypted ciphertext's should but
2599
+ * not private key encrypted ciphertext's.
2600
+ *
2601
+ * @access private
2602
+ * @param string $c
2603
+ * @return string
2604
+ */
2605
+ function _rsaes_pkcs1_v1_5_decrypt($c)
2606
+ {
2607
+ // Length checking
2608
+
2609
+ if (strlen($c) != $this->k) { // or if k < 11
2610
+ user_error('Decryption error');
2611
+ return false;
2612
+ }
2613
+
2614
+ // RSA decryption
2615
+
2616
+ $c = $this->_os2ip($c);
2617
+ $m = $this->_rsadp($c);
2618
+
2619
+ if ($m === false) {
2620
+ user_error('Decryption error');
2621
+ return false;
2622
+ }
2623
+ $em = $this->_i2osp($m, $this->k);
2624
+
2625
+ // EME-PKCS1-v1_5 decoding
2626
+
2627
+ if (ord($em[0]) != 0 || ord($em[1]) > 2) {
2628
+ user_error('Decryption error');
2629
+ return false;
2630
+ }
2631
+
2632
+ $ps = substr($em, 2, strpos($em, chr(0), 2) - 2);
2633
+ $m = substr($em, strlen($ps) + 3);
2634
+
2635
+ if (strlen($ps) < 8) {
2636
+ user_error('Decryption error');
2637
+ return false;
2638
+ }
2639
+
2640
+ // Output M
2641
+
2642
+ return $m;
2643
+ }
2644
+
2645
+ /**
2646
+ * EMSA-PSS-ENCODE
2647
+ *
2648
+ * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
2649
+ *
2650
+ * @access private
2651
+ * @param string $m
2652
+ * @param int $emBits
2653
+ */
2654
+ function _emsa_pss_encode($m, $emBits)
2655
+ {
2656
+ // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
2657
+ // be output.
2658
+
2659
+ $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8)
2660
+ $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
2661
+
2662
+ $mHash = $this->hash->hash($m);
2663
+ if ($emLen < $this->hLen + $sLen + 2) {
2664
+ user_error('Encoding error');
2665
+ return false;
2666
+ }
2667
+
2668
+ $salt = crypt_random_string($sLen);
2669
+ $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
2670
+ $h = $this->hash->hash($m2);
2671
+ $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2);
2672
+ $db = $ps . chr(1) . $salt;
2673
+ $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1);
2674
+ $maskedDB = $db ^ $dbMask;
2675
+ $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0];
2676
+ $em = $maskedDB . $h . chr(0xBC);
2677
+
2678
+ return $em;
2679
+ }
2680
+
2681
+ /**
2682
+ * EMSA-PSS-VERIFY
2683
+ *
2684
+ * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
2685
+ *
2686
+ * @access private
2687
+ * @param string $m
2688
+ * @param string $em
2689
+ * @param int $emBits
2690
+ * @return string
2691
+ */
2692
+ function _emsa_pss_verify($m, $em, $emBits)
2693
+ {
2694
+ // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
2695
+ // be output.
2696
+
2697
+ $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8);
2698
+ $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
2699
+
2700
+ $mHash = $this->hash->hash($m);
2701
+ if ($emLen < $this->hLen + $sLen + 2) {
2702
+ return false;
2703
+ }
2704
+
2705
+ if ($em[strlen($em) - 1] != chr(0xBC)) {
2706
+ return false;
2707
+ }
2708
+
2709
+ $maskedDB = substr($em, 0, -$this->hLen - 1);
2710
+ $h = substr($em, -$this->hLen - 1, $this->hLen);
2711
+ $temp = chr(0xFF << ($emBits & 7));
2712
+ if ((~$maskedDB[0] & $temp) != $temp) {
2713
+ return false;
2714
+ }
2715
+ $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1);
2716
+ $db = $maskedDB ^ $dbMask;
2717
+ $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0];
2718
+ $temp = $emLen - $this->hLen - $sLen - 2;
2719
+ if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) {
2720
+ return false;
2721
+ }
2722
+ $salt = substr($db, $temp + 1); // should be $sLen long
2723
+ $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
2724
+ $h2 = $this->hash->hash($m2);
2725
+ return $this->_equals($h, $h2);
2726
+ }
2727
+
2728
+ /**
2729
+ * RSASSA-PSS-SIGN
2730
+ *
2731
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
2732
+ *
2733
+ * @access private
2734
+ * @param string $m
2735
+ * @return string
2736
+ */
2737
+ function _rsassa_pss_sign($m)
2738
+ {
2739
+ // EMSA-PSS encoding
2740
+
2741
+ $em = $this->_emsa_pss_encode($m, 8 * $this->k - 1);
2742
+
2743
+ // RSA signature
2744
+
2745
+ $m = $this->_os2ip($em);
2746
+ $s = $this->_rsasp1($m);
2747
+ $s = $this->_i2osp($s, $this->k);
2748
+
2749
+ // Output the signature S
2750
+
2751
+ return $s;
2752
+ }
2753
+
2754
+ /**
2755
+ * RSASSA-PSS-VERIFY
2756
+ *
2757
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
2758
+ *
2759
+ * @access private
2760
+ * @param string $m
2761
+ * @param string $s
2762
+ * @return string
2763
+ */
2764
+ function _rsassa_pss_verify($m, $s)
2765
+ {
2766
+ // Length checking
2767
+
2768
+ if (strlen($s) != $this->k) {
2769
+ user_error('Invalid signature');
2770
+ return false;
2771
+ }
2772
+
2773
+ // RSA verification
2774
+
2775
+ $modBits = 8 * $this->k;
2776
+
2777
+ $s2 = $this->_os2ip($s);
2778
+ $m2 = $this->_rsavp1($s2);
2779
+ if ($m2 === false) {
2780
+ user_error('Invalid signature');
2781
+ return false;
2782
+ }
2783
+ $em = $this->_i2osp($m2, $modBits >> 3);
2784
+ if ($em === false) {
2785
+ user_error('Invalid signature');
2786
+ return false;
2787
+ }
2788
+
2789
+ // EMSA-PSS verification
2790
+
2791
+ return $this->_emsa_pss_verify($m, $em, $modBits - 1);
2792
+ }
2793
+
2794
+ /**
2795
+ * EMSA-PKCS1-V1_5-ENCODE
2796
+ *
2797
+ * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
2798
+ *
2799
+ * @access private
2800
+ * @param string $m
2801
+ * @param int $emLen
2802
+ * @return string
2803
+ */
2804
+ function _emsa_pkcs1_v1_5_encode($m, $emLen)
2805
+ {
2806
+ $h = $this->hash->hash($m);
2807
+ if ($h === false) {
2808
+ return false;
2809
+ }
2810
+
2811
+ // see http://tools.ietf.org/html/rfc3447#page-43
2812
+ switch ($this->hashName) {
2813
+ case 'md2':
2814
+ $t = pack('H*', '3020300c06082a864886f70d020205000410');
2815
+ break;
2816
+ case 'md5':
2817
+ $t = pack('H*', '3020300c06082a864886f70d020505000410');
2818
+ break;
2819
+ case 'sha1':
2820
+ $t = pack('H*', '3021300906052b0e03021a05000414');
2821
+ break;
2822
+ case 'sha256':
2823
+ $t = pack('H*', '3031300d060960864801650304020105000420');
2824
+ break;
2825
+ case 'sha384':
2826
+ $t = pack('H*', '3041300d060960864801650304020205000430');
2827
+ break;
2828
+ case 'sha512':
2829
+ $t = pack('H*', '3051300d060960864801650304020305000440');
2830
+ }
2831
+ $t.= $h;
2832
+ $tLen = strlen($t);
2833
+
2834
+ if ($emLen < $tLen + 11) {
2835
+ user_error('Intended encoded message length too short');
2836
+ return false;
2837
+ }
2838
+
2839
+ $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
2840
+
2841
+ $em = "\0\1$ps\0$t";
2842
+
2843
+ return $em;
2844
+ }
2845
+
2846
+ /**
2847
+ * RSASSA-PKCS1-V1_5-SIGN
2848
+ *
2849
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
2850
+ *
2851
+ * @access private
2852
+ * @param string $m
2853
+ * @return string
2854
+ */
2855
+ function _rsassa_pkcs1_v1_5_sign($m)
2856
+ {
2857
+ // EMSA-PKCS1-v1_5 encoding
2858
+
2859
+ $em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
2860
+ if ($em === false) {
2861
+ user_error('RSA modulus too short');
2862
+ return false;
2863
+ }
2864
+
2865
+ // RSA signature
2866
+
2867
+ $m = $this->_os2ip($em);
2868
+ $s = $this->_rsasp1($m);
2869
+ $s = $this->_i2osp($s, $this->k);
2870
+
2871
+ // Output the signature S
2872
+
2873
+ return $s;
2874
+ }
2875
+
2876
+ /**
2877
+ * RSASSA-PKCS1-V1_5-VERIFY
2878
+ *
2879
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
2880
+ *
2881
+ * @access private
2882
+ * @param string $m
2883
+ * @return string
2884
+ */
2885
+ function _rsassa_pkcs1_v1_5_verify($m, $s)
2886
+ {
2887
+ // Length checking
2888
+
2889
+ if (strlen($s) != $this->k) {
2890
+ user_error('Invalid signature');
2891
+ return false;
2892
+ }
2893
+
2894
+ // RSA verification
2895
+
2896
+ $s = $this->_os2ip($s);
2897
+ $m2 = $this->_rsavp1($s);
2898
+ if ($m2 === false) {
2899
+ user_error('Invalid signature');
2900
+ return false;
2901
+ }
2902
+ $em = $this->_i2osp($m2, $this->k);
2903
+ if ($em === false) {
2904
+ user_error('Invalid signature');
2905
+ return false;
2906
+ }
2907
+
2908
+ // EMSA-PKCS1-v1_5 encoding
2909
+
2910
+ $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
2911
+ if ($em2 === false) {
2912
+ user_error('RSA modulus too short');
2913
+ return false;
2914
+ }
2915
+
2916
+ // Compare
2917
+ return $this->_equals($em, $em2);
2918
+ }
2919
+
2920
+ /**
2921
+ * Set Encryption Mode
2922
+ *
2923
+ * Valid values include CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1.
2924
+ *
2925
+ * @access public
2926
+ * @param int $mode
2927
+ */
2928
+ function setEncryptionMode($mode)
2929
+ {
2930
+ $this->encryptionMode = $mode;
2931
+ }
2932
+
2933
+ /**
2934
+ * Set Signature Mode
2935
+ *
2936
+ * Valid values include CRYPT_RSA_SIGNATURE_PSS and CRYPT_RSA_SIGNATURE_PKCS1
2937
+ *
2938
+ * @access public
2939
+ * @param int $mode
2940
+ */
2941
+ function setSignatureMode($mode)
2942
+ {
2943
+ $this->signatureMode = $mode;
2944
+ }
2945
+
2946
+ /**
2947
+ * Set public key comment.
2948
+ *
2949
+ * @access public
2950
+ * @param string $comment
2951
+ */
2952
+ function setComment($comment)
2953
+ {
2954
+ $this->comment = $comment;
2955
+ }
2956
+
2957
+ /**
2958
+ * Get public key comment.
2959
+ *
2960
+ * @access public
2961
+ * @return string
2962
+ */
2963
+ function getComment()
2964
+ {
2965
+ return $this->comment;
2966
+ }
2967
+
2968
+ /**
2969
+ * Encryption
2970
+ *
2971
+ * Both CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1 both place limits on how long $plaintext can be.
2972
+ * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
2973
+ * be concatenated together.
2974
+ *
2975
+ * @see self::decrypt()
2976
+ * @access public
2977
+ * @param string $plaintext
2978
+ * @return string
2979
+ */
2980
+ function encrypt($plaintext)
2981
+ {
2982
+ switch ($this->encryptionMode) {
2983
+ case CRYPT_RSA_ENCRYPTION_NONE:
2984
+ $plaintext = str_split($plaintext, $this->k);
2985
+ $ciphertext = '';
2986
+ foreach ($plaintext as $m) {
2987
+ $ciphertext.= $this->_raw_encrypt($m);
2988
+ }
2989
+ return $ciphertext;
2990
+ case CRYPT_RSA_ENCRYPTION_PKCS1:
2991
+ $length = $this->k - 11;
2992
+ if ($length <= 0) {
2993
+ return false;
2994
+ }
2995
+
2996
+ $plaintext = str_split($plaintext, $length);
2997
+ $ciphertext = '';
2998
+ foreach ($plaintext as $m) {
2999
+ $ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m);
3000
+ }
3001
+ return $ciphertext;
3002
+ //case CRYPT_RSA_ENCRYPTION_OAEP:
3003
+ default:
3004
+ $length = $this->k - 2 * $this->hLen - 2;
3005
+ if ($length <= 0) {
3006
+ return false;
3007
+ }
3008
+
3009
+ $plaintext = str_split($plaintext, $length);
3010
+ $ciphertext = '';
3011
+ foreach ($plaintext as $m) {
3012
+ $ciphertext.= $this->_rsaes_oaep_encrypt($m);
3013
+ }
3014
+ return $ciphertext;
3015
+ }
3016
+ }
3017
+
3018
+ /**
3019
+ * Decryption
3020
+ *
3021
+ * @see self::encrypt()
3022
+ * @access public
3023
+ * @param string $plaintext
3024
+ * @return string
3025
+ */
3026
+ function decrypt($ciphertext)
3027
+ {
3028
+ if ($this->k <= 0) {
3029
+ return false;
3030
+ }
3031
+
3032
+ $ciphertext = str_split($ciphertext, $this->k);
3033
+ $ciphertext[count($ciphertext) - 1] = str_pad($ciphertext[count($ciphertext) - 1], $this->k, chr(0), STR_PAD_LEFT);
3034
+
3035
+ $plaintext = '';
3036
+
3037
+ switch ($this->encryptionMode) {
3038
+ case CRYPT_RSA_ENCRYPTION_NONE:
3039
+ $decrypt = '_raw_encrypt';
3040
+ break;
3041
+ case CRYPT_RSA_ENCRYPTION_PKCS1:
3042
+ $decrypt = '_rsaes_pkcs1_v1_5_decrypt';
3043
+ break;
3044
+ //case CRYPT_RSA_ENCRYPTION_OAEP:
3045
+ default:
3046
+ $decrypt = '_rsaes_oaep_decrypt';
3047
+ }
3048
+
3049
+ foreach ($ciphertext as $c) {
3050
+ $temp = $this->$decrypt($c);
3051
+ if ($temp === false) {
3052
+ return false;
3053
+ }
3054
+ $plaintext.= $temp;
3055
+ }
3056
+
3057
+ return $plaintext;
3058
+ }
3059
+
3060
+ /**
3061
+ * Create a signature
3062
+ *
3063
+ * @see self::verify()
3064
+ * @access public
3065
+ * @param string $message
3066
+ * @return string
3067
+ */
3068
+ function sign($message)
3069
+ {
3070
+ if (empty($this->modulus) || empty($this->exponent)) {
3071
+ return false;
3072
+ }
3073
+
3074
+ switch ($this->signatureMode) {
3075
+ case CRYPT_RSA_SIGNATURE_PKCS1:
3076
+ return $this->_rsassa_pkcs1_v1_5_sign($message);
3077
+ //case CRYPT_RSA_SIGNATURE_PSS:
3078
+ default:
3079
+ return $this->_rsassa_pss_sign($message);
3080
+ }
3081
+ }
3082
+
3083
+ /**
3084
+ * Verifies a signature
3085
+ *
3086
+ * @see self::sign()
3087
+ * @access public
3088
+ * @param string $message
3089
+ * @param string $signature
3090
+ * @return bool
3091
+ */
3092
+ function verify($message, $signature)
3093
+ {
3094
+ if (empty($this->modulus) || empty($this->exponent)) {
3095
+ return false;
3096
+ }
3097
+
3098
+ switch ($this->signatureMode) {
3099
+ case CRYPT_RSA_SIGNATURE_PKCS1:
3100
+ return $this->_rsassa_pkcs1_v1_5_verify($message, $signature);
3101
+ //case CRYPT_RSA_SIGNATURE_PSS:
3102
+ default:
3103
+ return $this->_rsassa_pss_verify($message, $signature);
3104
+ }
3105
+ }
3106
+
3107
+ /**
3108
+ * Extract raw BER from Base64 encoding
3109
+ *
3110
+ * @access private
3111
+ * @param string $str
3112
+ * @return string
3113
+ */
3114
+ function _extractBER($str)
3115
+ {
3116
+ /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
3117
+ * above and beyond the ceritificate.
3118
+ * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
3119
+ *
3120
+ * Bag Attributes
3121
+ * localKeyID: 01 00 00 00
3122
+ * subject=/O=organization/OU=org unit/CN=common name
3123
+ * issuer=/O=organization/CN=common name
3124
+ */
3125
+ $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
3126
+ // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
3127
+ $temp = preg_replace('#-+[^-]+-+#', '', $temp);
3128
+ // remove new lines
3129
+ $temp = str_replace(array("\r", "\n", ' '), '', $temp);
3130
+ $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
3131
+ return $temp != false ? $temp : $str;
3132
+ }
3133
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Random Number Generator
5
+ *
6
+ * The idea behind this function is that it can be easily replaced with your own crypt_random_string()
7
+ * function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
8
+ *
9
+ * PHP versions 4 and 5
10
+ *
11
+ * Here's a short example of how to use this library:
12
+ * <code>
13
+ * <?php
14
+ * include 'Crypt/Random.php';
15
+ *
16
+ * echo bin2hex(crypt_random_string(8));
17
+ * ?>
18
+ * </code>
19
+ *
20
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
21
+ * of this software and associated documentation files (the "Software"), to deal
22
+ * in the Software without restriction, including without limitation the rights
23
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24
+ * copies of the Software, and to permit persons to whom the Software is
25
+ * furnished to do so, subject to the following conditions:
26
+ *
27
+ * The above copyright notice and this permission notice shall be included in
28
+ * all copies or substantial portions of the Software.
29
+ *
30
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36
+ * THE SOFTWARE.
37
+ *
38
+ * @category Crypt
39
+ * @package Crypt_Random
40
+ * @author Jim Wigginton <terrafrost@php.net>
41
+ * @copyright 2007 Jim Wigginton
42
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
43
+ * @link http://phpseclib.sourceforge.net
44
+ */
45
+
46
+ // laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
47
+ // have phpseclib as a requirement as well. if you're developing such a program you may encounter
48
+ // a "Cannot redeclare crypt_random_string()" error.
49
+ if (!function_exists('crypt_random_string')) {
50
+ /**
51
+ * "Is Windows" test
52
+ *
53
+ * @access private
54
+ */
55
+ define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
56
+
57
+ /**
58
+ * Generate a random string.
59
+ *
60
+ * Although microoptimizations are generally discouraged as they impair readability this function is ripe with
61
+ * microoptimizations because this function has the potential of being called a huge number of times.
62
+ * eg. for RSA key generation.
63
+ *
64
+ * @param int $length
65
+ * @return string
66
+ * @access public
67
+ */
68
+ function crypt_random_string($length)
69
+ {
70
+ if (CRYPT_RANDOM_IS_WINDOWS) {
71
+ // method 1. prior to PHP 5.3, mcrypt_create_iv() would call rand() on windows
72
+ if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
73
+ return mcrypt_create_iv($length);
74
+ }
75
+ // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
76
+ // to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
77
+ // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
78
+ // call php_win32_get_random_bytes():
79
+ //
80
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
81
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
82
+ //
83
+ // php_win32_get_random_bytes() is defined thusly:
84
+ //
85
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
86
+ //
87
+ // we're calling it, all the same, in the off chance that the mcrypt extension is not available
88
+ if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
89
+ return openssl_random_pseudo_bytes($length);
90
+ }
91
+ } else {
92
+ // method 1. the fastest
93
+ if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
94
+ return openssl_random_pseudo_bytes($length);
95
+ }
96
+ // method 2
97
+ static $fp = true;
98
+ if ($fp === true) {
99
+ // warning's will be output unles the error suppression operator is used. errors such as
100
+ // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
101
+ $fp = @fopen('/dev/urandom', 'rb');
102
+ }
103
+ if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
104
+ return fread($fp, $length);
105
+ }
106
+ // method 3. pretty much does the same thing as method 2 per the following url:
107
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
108
+ // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
109
+ // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
110
+ // restrictions or some such
111
+ if (extension_loaded('mcrypt')) {
112
+ return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
113
+ }
114
+ }
115
+ // at this point we have no choice but to use a pure-PHP CSPRNG
116
+
117
+ // cascade entropy across multiple PHP instances by fixing the session and collecting all
118
+ // environmental variables, including the previous session data and the current session
119
+ // data.
120
+ //
121
+ // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
122
+ // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
123
+ // PHP isn't low level to be able to use those as sources and on a web server there's not likely
124
+ // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
125
+ // however, a ton of people visiting the website. obviously you don't want to base your seeding
126
+ // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
127
+ // by the user and (2) this isn't just looking at the data sent by the current user - it's based
128
+ // on the data sent by all users. one user requests the page and a hash of their info is saved.
129
+ // another user visits the page and the serialization of their data is utilized along with the
130
+ // server envirnment stuff and a hash of the previous http request data (which itself utilizes
131
+ // a hash of the session data before that). certainly an attacker should be assumed to have
132
+ // full control over his own http requests. he, however, is not going to have control over
133
+ // everyone's http requests.
134
+ static $crypto = false, $v;
135
+ if ($crypto === false) {
136
+ // save old session data
137
+ $old_session_id = session_id();
138
+ $old_use_cookies = ini_get('session.use_cookies');
139
+ $old_session_cache_limiter = session_cache_limiter();
140
+ $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
141
+ if ($old_session_id != '') {
142
+ session_write_close();
143
+ }
144
+
145
+ session_id(1);
146
+ ini_set('session.use_cookies', 0);
147
+ session_cache_limiter('');
148
+ session_start();
149
+
150
+ $v = $seed = $_SESSION['seed'] = pack('H*', sha1(
151
+ (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
152
+ (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
153
+ (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
154
+ (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
155
+ phpseclib_safe_serialize($GLOBALS) .
156
+ phpseclib_safe_serialize($_SESSION) .
157
+ phpseclib_safe_serialize($_OLD_SESSION)
158
+ ));
159
+ if (!isset($_SESSION['count'])) {
160
+ $_SESSION['count'] = 0;
161
+ }
162
+ $_SESSION['count']++;
163
+
164
+ session_write_close();
165
+
166
+ // restore old session data
167
+ if ($old_session_id != '') {
168
+ session_id($old_session_id);
169
+ session_start();
170
+ ini_set('session.use_cookies', $old_use_cookies);
171
+ session_cache_limiter($old_session_cache_limiter);
172
+ } else {
173
+ if ($_OLD_SESSION !== false) {
174
+ $_SESSION = $_OLD_SESSION;
175
+ unset($_OLD_SESSION);
176
+ } else {
177
+ unset($_SESSION);
178
+ }
179
+ }
180
+
181
+ // in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
182
+ // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
183
+ // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
184
+ // original hash and the current hash. we'll be emulating that. for more info see the following URL:
185
+ //
186
+ // http://tools.ietf.org/html/rfc4253#section-7.2
187
+ //
188
+ // see the is_string($crypto) part for an example of how to expand the keys
189
+ $key = pack('H*', sha1($seed . 'A'));
190
+ $iv = pack('H*', sha1($seed . 'C'));
191
+
192
+ // ciphers are used as per the nist.gov link below. also, see this link:
193
+ //
194
+ // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
195
+ switch (true) {
196
+ case phpseclib_resolve_include_path('Crypt/AES.php'):
197
+ if (!class_exists('Crypt_AES')) {
198
+ include_once 'AES.php';
199
+ }
200
+ $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
201
+ break;
202
+ case phpseclib_resolve_include_path('Crypt/Twofish.php'):
203
+ if (!class_exists('Crypt_Twofish')) {
204
+ include_once 'Twofish.php';
205
+ }
206
+ $crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
207
+ break;
208
+ case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
209
+ if (!class_exists('Crypt_Blowfish')) {
210
+ include_once 'Blowfish.php';
211
+ }
212
+ $crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
213
+ break;
214
+ case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
215
+ if (!class_exists('Crypt_TripleDES')) {
216
+ include_once 'TripleDES.php';
217
+ }
218
+ $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
219
+ break;
220
+ case phpseclib_resolve_include_path('Crypt/DES.php'):
221
+ if (!class_exists('Crypt_DES')) {
222
+ include_once 'DES.php';
223
+ }
224
+ $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
225
+ break;
226
+ case phpseclib_resolve_include_path('Crypt/RC4.php'):
227
+ if (!class_exists('Crypt_RC4')) {
228
+ include_once 'RC4.php';
229
+ }
230
+ $crypto = new Crypt_RC4();
231
+ break;
232
+ default:
233
+ user_error('crypt_random_string requires at least one symmetric cipher be loaded');
234
+ return false;
235
+ }
236
+
237
+ $crypto->setKey($key);
238
+ $crypto->setIV($iv);
239
+ $crypto->enableContinuousBuffer();
240
+ }
241
+
242
+ //return $crypto->encrypt(str_repeat("\0", $length));
243
+
244
+ // the following is based off of ANSI X9.31:
245
+ //
246
+ // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
247
+ //
248
+ // OpenSSL uses that same standard for it's random numbers:
249
+ //
250
+ // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
251
+ // (do a search for "ANS X9.31 A.2.4")
252
+ $result = '';
253
+ while (strlen($result) < $length) {
254
+ $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
255
+ $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
256
+ $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
257
+ $result.= $r;
258
+ }
259
+ return substr($result, 0, $length);
260
+ }
261
+ }
262
+
263
+ if (!function_exists('phpseclib_safe_serialize')) {
264
+ /**
265
+ * Safely serialize variables
266
+ *
267
+ * If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
268
+ * PHP 5.3 will emit a warning.
269
+ *
270
+ * @param mixed $arr
271
+ * @access public
272
+ */
273
+ function phpseclib_safe_serialize(&$arr)
274
+ {
275
+ if (is_object($arr)) {
276
+ return '';
277
+ }
278
+ if (!is_array($arr)) {
279
+ return serialize($arr);
280
+ }
281
+ // prevent circular array recursion
282
+ if (isset($arr['__phpseclib_marker'])) {
283
+ return '';
284
+ }
285
+ $safearr = array();
286
+ $arr['__phpseclib_marker'] = true;
287
+ foreach (array_keys($arr) as $key) {
288
+ // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
289
+ if ($key !== '__phpseclib_marker') {
290
+ $safearr[$key] = phpseclib_safe_serialize($arr[$key]);
291
+ }
292
+ }
293
+ unset($arr['__phpseclib_marker']);
294
+ return serialize($safearr);
295
+ }
296
+ }
297
+
298
+ if (!function_exists('phpseclib_resolve_include_path')) {
299
+ /**
300
+ * Resolve filename against the include path.
301
+ *
302
+ * Wrapper around stream_resolve_include_path() (which was introduced in
303
+ * PHP 5.3.2) with fallback implementation for earlier PHP versions.
304
+ *
305
+ * @param string $filename
306
+ * @return string|false
307
+ * @access public
308
+ */
309
+ function phpseclib_resolve_include_path($filename)
310
+ {
311
+ if (function_exists('stream_resolve_include_path')) {
312
+ return stream_resolve_include_path($filename);
313
+ }
314
+
315
+ // handle non-relative paths
316
+ if (file_exists($filename)) {
317
+ return realpath($filename);
318
+ }
319
+
320
+ $paths = PATH_SEPARATOR == ':' ?
321
+ preg_split('#(?<!phar):#', get_include_path()) :
322
+ explode(PATH_SEPARATOR, get_include_path());
323
+ foreach ($paths as $prefix) {
324
+ // path's specified in include_path don't always end in /
325
+ $ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
326
+ $file = $prefix . $ds . $filename;
327
+ if (file_exists($file)) {
328
+ return realpath($file);
329
+ }
330
+ }
331
+
332
+ return false;
333
+ }
334
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php ADDED
@@ -0,0 +1,1050 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of Rijndael.
5
+ *
6
+ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
11
+ * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12
+ * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
13
+ * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
14
+ * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
15
+ *
16
+ * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
17
+ * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
18
+ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
19
+ * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224. Indeed, 160 and 224
20
+ * are first defined as valid key / block lengths in
21
+ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
22
+ * Extensions: Other block and Cipher Key lengths.
23
+ * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
24
+ *
25
+ * {@internal The variable names are the same as those in
26
+ * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
27
+ *
28
+ * Here's a short example of how to use this library:
29
+ * <code>
30
+ * <?php
31
+ * include 'Crypt/Rijndael.php';
32
+ *
33
+ * $rijndael = new Crypt_Rijndael();
34
+ *
35
+ * $rijndael->setKey('abcdefghijklmnop');
36
+ *
37
+ * $size = 10 * 1024;
38
+ * $plaintext = '';
39
+ * for ($i = 0; $i < $size; $i++) {
40
+ * $plaintext.= 'a';
41
+ * }
42
+ *
43
+ * echo $rijndael->decrypt($rijndael->encrypt($plaintext));
44
+ * ?>
45
+ * </code>
46
+ *
47
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
48
+ * of this software and associated documentation files (the "Software"), to deal
49
+ * in the Software without restriction, including without limitation the rights
50
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
51
+ * copies of the Software, and to permit persons to whom the Software is
52
+ * furnished to do so, subject to the following conditions:
53
+ *
54
+ * The above copyright notice and this permission notice shall be included in
55
+ * all copies or substantial portions of the Software.
56
+ *
57
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
59
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
60
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
61
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63
+ * THE SOFTWARE.
64
+ *
65
+ * @category Crypt
66
+ * @package Crypt_Rijndael
67
+ * @author Jim Wigginton <terrafrost@php.net>
68
+ * @copyright 2008 Jim Wigginton
69
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
70
+ * @link http://phpseclib.sourceforge.net
71
+ */
72
+
73
+ /**
74
+ * Include Crypt_Base
75
+ *
76
+ * Base cipher class
77
+ */
78
+ if (!class_exists('Crypt_Base')) {
79
+ include_once 'Base.php';
80
+ }
81
+
82
+ /**#@+
83
+ * @access public
84
+ * @see self::encrypt()
85
+ * @see self::decrypt()
86
+ */
87
+ /**
88
+ * Encrypt / decrypt using the Counter mode.
89
+ *
90
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
91
+ *
92
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
93
+ */
94
+ define('CRYPT_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR);
95
+ /**
96
+ * Encrypt / decrypt using the Electronic Code Book mode.
97
+ *
98
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
99
+ */
100
+ define('CRYPT_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB);
101
+ /**
102
+ * Encrypt / decrypt using the Code Book Chaining mode.
103
+ *
104
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
105
+ */
106
+ define('CRYPT_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC);
107
+ /**
108
+ * Encrypt / decrypt using the Cipher Feedback mode.
109
+ *
110
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
111
+ */
112
+ define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB);
113
+ /**
114
+ * Encrypt / decrypt using the Cipher Feedback mode.
115
+ *
116
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
117
+ */
118
+ define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
119
+ /**#@-*/
120
+
121
+ /**
122
+ * Pure-PHP implementation of Rijndael.
123
+ *
124
+ * @package Crypt_Rijndael
125
+ * @author Jim Wigginton <terrafrost@php.net>
126
+ * @access public
127
+ */
128
+ class Crypt_Rijndael extends Crypt_Base
129
+ {
130
+ /**
131
+ * The namespace used by the cipher for its constants.
132
+ *
133
+ * @see Crypt_Base::const_namespace
134
+ * @var string
135
+ * @access private
136
+ */
137
+ var $const_namespace = 'RIJNDAEL';
138
+
139
+ /**
140
+ * The mcrypt specific name of the cipher
141
+ *
142
+ * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
143
+ * Crypt_Rijndael determines automatically whether mcrypt is useable
144
+ * or not for the current $block_size/$key_length.
145
+ * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
146
+ *
147
+ * @see Crypt_Base::cipher_name_mcrypt
148
+ * @see Crypt_Base::engine
149
+ * @see self::isValidEngine()
150
+ * @var string
151
+ * @access private
152
+ */
153
+ var $cipher_name_mcrypt = 'rijndael-128';
154
+
155
+ /**
156
+ * The default salt used by setPassword()
157
+ *
158
+ * @see Crypt_Base::password_default_salt
159
+ * @see Crypt_Base::setPassword()
160
+ * @var string
161
+ * @access private
162
+ */
163
+ var $password_default_salt = 'phpseclib';
164
+
165
+ /**
166
+ * The Key Schedule
167
+ *
168
+ * @see self::_setup()
169
+ * @var array
170
+ * @access private
171
+ */
172
+ var $w;
173
+
174
+ /**
175
+ * The Inverse Key Schedule
176
+ *
177
+ * @see self::_setup()
178
+ * @var array
179
+ * @access private
180
+ */
181
+ var $dw;
182
+
183
+ /**
184
+ * The Block Length divided by 32
185
+ *
186
+ * @see self::setBlockLength()
187
+ * @var int
188
+ * @access private
189
+ * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
190
+ * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
191
+ * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
192
+ * of that, we'll just precompute it once.
193
+ */
194
+ var $Nb = 4;
195
+
196
+ /**
197
+ * The Key Length (in bytes)
198
+ *
199
+ * @see self::setKeyLength()
200
+ * @var int
201
+ * @access private
202
+ * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
203
+ * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
204
+ * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
205
+ * of that, we'll just precompute it once.
206
+ */
207
+ var $key_length = 16;
208
+
209
+ /**
210
+ * The Key Length divided by 32
211
+ *
212
+ * @see self::setKeyLength()
213
+ * @var int
214
+ * @access private
215
+ * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
216
+ */
217
+ var $Nk = 4;
218
+
219
+ /**
220
+ * The Number of Rounds
221
+ *
222
+ * @var int
223
+ * @access private
224
+ * @internal The max value is 14, the min value is 10.
225
+ */
226
+ var $Nr;
227
+
228
+ /**
229
+ * Shift offsets
230
+ *
231
+ * @var array
232
+ * @access private
233
+ */
234
+ var $c;
235
+
236
+ /**
237
+ * Holds the last used key- and block_size information
238
+ *
239
+ * @var array
240
+ * @access private
241
+ */
242
+ var $kl;
243
+
244
+ /**
245
+ * Sets the key.
246
+ *
247
+ * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
248
+ * whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
249
+ * up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the
250
+ * excess bits.
251
+ *
252
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
253
+ *
254
+ * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
255
+ *
256
+ * @see Crypt_Base:setKey()
257
+ * @see self::setKeyLength()
258
+ * @access public
259
+ * @param string $key
260
+ */
261
+ function setKey($key)
262
+ {
263
+ if (!$this->explicit_key_length) {
264
+ $length = strlen($key);
265
+ switch (true) {
266
+ case $length <= 16:
267
+ $this->key_size = 16;
268
+ break;
269
+ case $length <= 20:
270
+ $this->key_size = 20;
271
+ break;
272
+ case $length <= 24:
273
+ $this->key_size = 24;
274
+ break;
275
+ case $length <= 28:
276
+ $this->key_size = 28;
277
+ break;
278
+ default:
279
+ $this->key_size = 32;
280
+ }
281
+ }
282
+ parent::setKey($key);
283
+ }
284
+
285
+ /**
286
+ * Sets the key length
287
+ *
288
+ * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
289
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
290
+ *
291
+ * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
292
+ * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
293
+ * 192/256 bits as, for example, mcrypt will do.
294
+ *
295
+ * That said, if you want be compatible with other Rijndael and AES implementations,
296
+ * you should not setKeyLength(160) or setKeyLength(224).
297
+ *
298
+ * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
299
+ * the mcrypt php extension, even if available.
300
+ * This results then in slower encryption.
301
+ *
302
+ * @access public
303
+ * @param int $length
304
+ */
305
+ function setKeyLength($length)
306
+ {
307
+ switch (true) {
308
+ case $length <= 128:
309
+ $this->key_length = 16;
310
+ break;
311
+ case $length <= 160:
312
+ $this->key_length = 20;
313
+ break;
314
+ case $length <= 192:
315
+ $this->key_length = 24;
316
+ break;
317
+ case $length <= 224:
318
+ $this->key_length = 28;
319
+ break;
320
+ default:
321
+ $this->key_length = 32;
322
+ }
323
+
324
+ parent::setKeyLength($length);
325
+ }
326
+
327
+ /**
328
+ * Sets the block length
329
+ *
330
+ * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
331
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
332
+ *
333
+ * @access public
334
+ * @param int $length
335
+ */
336
+ function setBlockLength($length)
337
+ {
338
+ $length >>= 5;
339
+ if ($length > 8) {
340
+ $length = 8;
341
+ } elseif ($length < 4) {
342
+ $length = 4;
343
+ }
344
+ $this->Nb = $length;
345
+ $this->block_size = $length << 2;
346
+ $this->changed = true;
347
+ $this->_setEngine();
348
+ }
349
+
350
+ /**
351
+ * Test for engine validity
352
+ *
353
+ * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
354
+ *
355
+ * @see Crypt_Base::Crypt_Base()
356
+ * @param int $engine
357
+ * @access public
358
+ * @return bool
359
+ */
360
+ function isValidEngine($engine)
361
+ {
362
+ switch ($engine) {
363
+ case CRYPT_ENGINE_OPENSSL:
364
+ if ($this->block_size != 16) {
365
+ return false;
366
+ }
367
+ $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
368
+ $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
369
+ break;
370
+ case CRYPT_ENGINE_MCRYPT:
371
+ $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
372
+ if ($this->key_length % 8) { // is it a 160/224-bit key?
373
+ // mcrypt is not usable for them, only for 128/192/256-bit keys
374
+ return false;
375
+ }
376
+ }
377
+
378
+ return parent::isValidEngine($engine);
379
+ }
380
+
381
+ /**
382
+ * Encrypts a block
383
+ *
384
+ * @access private
385
+ * @param string $in
386
+ * @return string
387
+ */
388
+ function _encryptBlock($in)
389
+ {
390
+ static $tables;
391
+ if (empty($tables)) {
392
+ $tables = &$this->_getTables();
393
+ }
394
+ $t0 = $tables[0];
395
+ $t1 = $tables[1];
396
+ $t2 = $tables[2];
397
+ $t3 = $tables[3];
398
+ $sbox = $tables[4];
399
+
400
+ $state = array();
401
+ $words = unpack('N*', $in);
402
+
403
+ $c = $this->c;
404
+ $w = $this->w;
405
+ $Nb = $this->Nb;
406
+ $Nr = $this->Nr;
407
+
408
+ // addRoundKey
409
+ $wc = $Nb - 1;
410
+ foreach ($words as $word) {
411
+ $state[] = $word ^ $w[++$wc];
412
+ }
413
+
414
+ // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
415
+ // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
416
+ // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
417
+ // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
418
+ // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
419
+ // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
420
+
421
+ // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
422
+ $temp = array();
423
+ for ($round = 1; $round < $Nr; ++$round) {
424
+ $i = 0; // $c[0] == 0
425
+ $j = $c[1];
426
+ $k = $c[2];
427
+ $l = $c[3];
428
+
429
+ while ($i < $Nb) {
430
+ $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
431
+ $t1[$state[$j] >> 16 & 0x000000FF] ^
432
+ $t2[$state[$k] >> 8 & 0x000000FF] ^
433
+ $t3[$state[$l] & 0x000000FF] ^
434
+ $w[++$wc];
435
+ ++$i;
436
+ $j = ($j + 1) % $Nb;
437
+ $k = ($k + 1) % $Nb;
438
+ $l = ($l + 1) % $Nb;
439
+ }
440
+ $state = $temp;
441
+ }
442
+
443
+ // subWord
444
+ for ($i = 0; $i < $Nb; ++$i) {
445
+ $state[$i] = $sbox[$state[$i] & 0x000000FF] |
446
+ ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) |
447
+ ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
448
+ ($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
449
+ }
450
+
451
+ // shiftRows + addRoundKey
452
+ $i = 0; // $c[0] == 0
453
+ $j = $c[1];
454
+ $k = $c[2];
455
+ $l = $c[3];
456
+ while ($i < $Nb) {
457
+ $temp[$i] = ($state[$i] & 0xFF000000) ^
458
+ ($state[$j] & 0x00FF0000) ^
459
+ ($state[$k] & 0x0000FF00) ^
460
+ ($state[$l] & 0x000000FF) ^
461
+ $w[$i];
462
+ ++$i;
463
+ $j = ($j + 1) % $Nb;
464
+ $k = ($k + 1) % $Nb;
465
+ $l = ($l + 1) % $Nb;
466
+ }
467
+
468
+ switch ($Nb) {
469
+ case 8:
470
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
471
+ case 7:
472
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
473
+ case 6:
474
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
475
+ case 5:
476
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
477
+ default:
478
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Decrypts a block
484
+ *
485
+ * @access private
486
+ * @param string $in
487
+ * @return string
488
+ */
489
+ function _decryptBlock($in)
490
+ {
491
+ static $invtables;
492
+ if (empty($invtables)) {
493
+ $invtables = &$this->_getInvTables();
494
+ }
495
+ $dt0 = $invtables[0];
496
+ $dt1 = $invtables[1];
497
+ $dt2 = $invtables[2];
498
+ $dt3 = $invtables[3];
499
+ $isbox = $invtables[4];
500
+
501
+ $state = array();
502
+ $words = unpack('N*', $in);
503
+
504
+ $c = $this->c;
505
+ $dw = $this->dw;
506
+ $Nb = $this->Nb;
507
+ $Nr = $this->Nr;
508
+
509
+ // addRoundKey
510
+ $wc = $Nb - 1;
511
+ foreach ($words as $word) {
512
+ $state[] = $word ^ $dw[++$wc];
513
+ }
514
+
515
+ $temp = array();
516
+ for ($round = $Nr - 1; $round > 0; --$round) {
517
+ $i = 0; // $c[0] == 0
518
+ $j = $Nb - $c[1];
519
+ $k = $Nb - $c[2];
520
+ $l = $Nb - $c[3];
521
+
522
+ while ($i < $Nb) {
523
+ $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
524
+ $dt1[$state[$j] >> 16 & 0x000000FF] ^
525
+ $dt2[$state[$k] >> 8 & 0x000000FF] ^
526
+ $dt3[$state[$l] & 0x000000FF] ^
527
+ $dw[++$wc];
528
+ ++$i;
529
+ $j = ($j + 1) % $Nb;
530
+ $k = ($k + 1) % $Nb;
531
+ $l = ($l + 1) % $Nb;
532
+ }
533
+ $state = $temp;
534
+ }
535
+
536
+ // invShiftRows + invSubWord + addRoundKey
537
+ $i = 0; // $c[0] == 0
538
+ $j = $Nb - $c[1];
539
+ $k = $Nb - $c[2];
540
+ $l = $Nb - $c[3];
541
+
542
+ while ($i < $Nb) {
543
+ $word = ($state[$i] & 0xFF000000) |
544
+ ($state[$j] & 0x00FF0000) |
545
+ ($state[$k] & 0x0000FF00) |
546
+ ($state[$l] & 0x000000FF);
547
+
548
+ $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] |
549
+ ($isbox[$word >> 8 & 0x000000FF] << 8) |
550
+ ($isbox[$word >> 16 & 0x000000FF] << 16) |
551
+ ($isbox[$word >> 24 & 0x000000FF] << 24));
552
+ ++$i;
553
+ $j = ($j + 1) % $Nb;
554
+ $k = ($k + 1) % $Nb;
555
+ $l = ($l + 1) % $Nb;
556
+ }
557
+
558
+ switch ($Nb) {
559
+ case 8:
560
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
561
+ case 7:
562
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
563
+ case 6:
564
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
565
+ case 5:
566
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
567
+ default:
568
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
569
+ }
570
+ }
571
+
572
+ /**
573
+ * Setup the key (expansion)
574
+ *
575
+ * @see Crypt_Base::_setupKey()
576
+ * @access private
577
+ */
578
+ function _setupKey()
579
+ {
580
+ // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
581
+ // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
582
+ static $rcon = array(0,
583
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
584
+ 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
585
+ 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
586
+ 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
587
+ 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
588
+ 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
589
+ );
590
+
591
+ if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
592
+ // already expanded
593
+ return;
594
+ }
595
+ $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
596
+
597
+ $this->Nk = $this->key_length >> 2;
598
+ // see Rijndael-ammended.pdf#page=44
599
+ $this->Nr = max($this->Nk, $this->Nb) + 6;
600
+
601
+ // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
602
+ // "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
603
+ // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
604
+ // "Table 2: Shift offsets for different block lengths"
605
+ switch ($this->Nb) {
606
+ case 4:
607
+ case 5:
608
+ case 6:
609
+ $this->c = array(0, 1, 2, 3);
610
+ break;
611
+ case 7:
612
+ $this->c = array(0, 1, 2, 4);
613
+ break;
614
+ case 8:
615
+ $this->c = array(0, 1, 3, 4);
616
+ }
617
+
618
+ $w = array_values(unpack('N*words', $this->key));
619
+
620
+ $length = $this->Nb * ($this->Nr + 1);
621
+ for ($i = $this->Nk; $i < $length; $i++) {
622
+ $temp = $w[$i - 1];
623
+ if ($i % $this->Nk == 0) {
624
+ // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
625
+ // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
626
+ // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
627
+ // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
628
+ $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
629
+ $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
630
+ } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
631
+ $temp = $this->_subWord($temp);
632
+ }
633
+ $w[$i] = $w[$i - $this->Nk] ^ $temp;
634
+ }
635
+
636
+ // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
637
+ // and generate the inverse key schedule. more specifically,
638
+ // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
639
+ // "The key expansion for the Inverse Cipher is defined as follows:
640
+ // 1. Apply the Key Expansion.
641
+ // 2. Apply InvMixColumn to all Round Keys except the first and the last one."
642
+ // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
643
+ list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
644
+ $temp = $this->w = $this->dw = array();
645
+ for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
646
+ if ($col == $this->Nb) {
647
+ if ($row == 0) {
648
+ $this->dw[0] = $this->w[0];
649
+ } else {
650
+ // subWord + invMixColumn + invSubWord = invMixColumn
651
+ $j = 0;
652
+ while ($j < $this->Nb) {
653
+ $dw = $this->_subWord($this->w[$row][$j]);
654
+ $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
655
+ $dt1[$dw >> 16 & 0x000000FF] ^
656
+ $dt2[$dw >> 8 & 0x000000FF] ^
657
+ $dt3[$dw & 0x000000FF];
658
+ $j++;
659
+ }
660
+ $this->dw[$row] = $temp;
661
+ }
662
+
663
+ $col = 0;
664
+ $row++;
665
+ }
666
+ $this->w[$row][$col] = $w[$i];
667
+ }
668
+
669
+ $this->dw[$row] = $this->w[$row];
670
+
671
+ // Converting to 1-dim key arrays (both ascending)
672
+ $this->dw = array_reverse($this->dw);
673
+ $w = array_pop($this->w);
674
+ $dw = array_pop($this->dw);
675
+ foreach ($this->w as $r => $wr) {
676
+ foreach ($wr as $c => $wc) {
677
+ $w[] = $wc;
678
+ $dw[] = $this->dw[$r][$c];
679
+ }
680
+ }
681
+ $this->w = $w;
682
+ $this->dw = $dw;
683
+ }
684
+
685
+ /**
686
+ * Performs S-Box substitutions
687
+ *
688
+ * @access private
689
+ * @param int $word
690
+ */
691
+ function _subWord($word)
692
+ {
693
+ static $sbox;
694
+ if (empty($sbox)) {
695
+ list(, , , , $sbox) = $this->_getTables();
696
+ }
697
+
698
+ return $sbox[$word & 0x000000FF] |
699
+ ($sbox[$word >> 8 & 0x000000FF] << 8) |
700
+ ($sbox[$word >> 16 & 0x000000FF] << 16) |
701
+ ($sbox[$word >> 24 & 0x000000FF] << 24);
702
+ }
703
+
704
+ /**
705
+ * Provides the mixColumns and sboxes tables
706
+ *
707
+ * @see Crypt_Rijndael:_encryptBlock()
708
+ * @see Crypt_Rijndael:_setupInlineCrypt()
709
+ * @see Crypt_Rijndael:_subWord()
710
+ * @access private
711
+ * @return array &$tables
712
+ */
713
+ function &_getTables()
714
+ {
715
+ static $tables;
716
+ if (empty($tables)) {
717
+ // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
718
+ // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
719
+ // those are the names we'll use.
720
+ $t3 = array_map('intval', array(
721
+ // with array_map('intval', ...) we ensure we have only int's and not
722
+ // some slower floats converted by php automatically on high values
723
+ 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
724
+ 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
725
+ 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
726
+ 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
727
+ 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
728
+ 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
729
+ 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
730
+ 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
731
+ 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
732
+ 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
733
+ 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
734
+ 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
735
+ 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
736
+ 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
737
+ 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
738
+ 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
739
+ 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
740
+ 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
741
+ 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
742
+ 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
743
+ 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
744
+ 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
745
+ 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
746
+ 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
747
+ 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
748
+ 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
749
+ 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
750
+ 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
751
+ 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
752
+ 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
753
+ 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
754
+ 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
755
+ ));
756
+
757
+ foreach ($t3 as $t3i) {
758
+ $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF);
759
+ $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
760
+ $t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
761
+ }
762
+
763
+ $tables = array(
764
+ // The Precomputed mixColumns tables t0 - t3
765
+ $t0,
766
+ $t1,
767
+ $t2,
768
+ $t3,
769
+ // The SubByte S-Box
770
+ array(
771
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
772
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
773
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
774
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
775
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
776
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
777
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
778
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
779
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
780
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
781
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
782
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
783
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
784
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
785
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
786
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
787
+ )
788
+ );
789
+ }
790
+ return $tables;
791
+ }
792
+
793
+ /**
794
+ * Provides the inverse mixColumns and inverse sboxes tables
795
+ *
796
+ * @see Crypt_Rijndael:_decryptBlock()
797
+ * @see Crypt_Rijndael:_setupInlineCrypt()
798
+ * @see Crypt_Rijndael:_setupKey()
799
+ * @access private
800
+ * @return array &$tables
801
+ */
802
+ function &_getInvTables()
803
+ {
804
+ static $tables;
805
+ if (empty($tables)) {
806
+ $dt3 = array_map('intval', array(
807
+ 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
808
+ 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
809
+ 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
810
+ 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
811
+ 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
812
+ 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
813
+ 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
814
+ 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
815
+ 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
816
+ 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
817
+ 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
818
+ 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
819
+ 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
820
+ 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
821
+ 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
822
+ 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
823
+ 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
824
+ 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
825
+ 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
826
+ 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
827
+ 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
828
+ 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
829
+ 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
830
+ 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
831
+ 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
832
+ 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
833
+ 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
834
+ 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
835
+ 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
836
+ 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
837
+ 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
838
+ 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
839
+ ));
840
+
841
+ foreach ($dt3 as $dt3i) {
842
+ $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
843
+ $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
844
+ $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
845
+ };
846
+
847
+ $tables = array(
848
+ // The Precomputed inverse mixColumns tables dt0 - dt3
849
+ $dt0,
850
+ $dt1,
851
+ $dt2,
852
+ $dt3,
853
+ // The inverse SubByte S-Box
854
+ array(
855
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
856
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
857
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
858
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
859
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
860
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
861
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
862
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
863
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
864
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
865
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
866
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
867
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
868
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
869
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
870
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
871
+ )
872
+ );
873
+ }
874
+ return $tables;
875
+ }
876
+
877
+ /**
878
+ * Setup the performance-optimized function for de/encrypt()
879
+ *
880
+ * @see Crypt_Base::_setupInlineCrypt()
881
+ * @access private
882
+ */
883
+ function _setupInlineCrypt()
884
+ {
885
+ // Note: _setupInlineCrypt() will be called only if $this->changed === true
886
+ // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
887
+ // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
888
+
889
+ $lambda_functions =& Crypt_Rijndael::_getLambdaFunctions();
890
+
891
+ // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
892
+ // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
893
+ // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
894
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
895
+
896
+ // Generation of a uniqe hash for our generated code
897
+ $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
898
+ if ($gen_hi_opt_code) {
899
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
900
+ }
901
+
902
+ if (!isset($lambda_functions[$code_hash])) {
903
+ switch (true) {
904
+ case $gen_hi_opt_code:
905
+ // The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
906
+ $w = $this->w;
907
+ $dw = $this->dw;
908
+ $init_encrypt = '';
909
+ $init_decrypt = '';
910
+ break;
911
+ default:
912
+ for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
913
+ $w[] = '$w[' . $i . ']';
914
+ $dw[] = '$dw[' . $i . ']';
915
+ }
916
+ $init_encrypt = '$w = $self->w;';
917
+ $init_decrypt = '$dw = $self->dw;';
918
+ }
919
+
920
+ $Nr = $this->Nr;
921
+ $Nb = $this->Nb;
922
+ $c = $this->c;
923
+
924
+ // Generating encrypt code:
925
+ $init_encrypt.= '
926
+ static $tables;
927
+ if (empty($tables)) {
928
+ $tables = &$self->_getTables();
929
+ }
930
+ $t0 = $tables[0];
931
+ $t1 = $tables[1];
932
+ $t2 = $tables[2];
933
+ $t3 = $tables[3];
934
+ $sbox = $tables[4];
935
+ ';
936
+
937
+ $s = 'e';
938
+ $e = 's';
939
+ $wc = $Nb - 1;
940
+
941
+ // Preround: addRoundKey
942
+ $encrypt_block = '$in = unpack("N*", $in);'."\n";
943
+ for ($i = 0; $i < $Nb; ++$i) {
944
+ $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";
945
+ }
946
+
947
+ // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
948
+ for ($round = 1; $round < $Nr; ++$round) {
949
+ list($s, $e) = array($e, $s);
950
+ for ($i = 0; $i < $Nb; ++$i) {
951
+ $encrypt_block.=
952
+ '$'.$e.$i.' =
953
+ $t0[($'.$s.$i .' >> 24) & 0xff] ^
954
+ $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
955
+ $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^
956
+ $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^
957
+ '.$w[++$wc].";\n";
958
+ }
959
+ }
960
+
961
+ // Finalround: subWord + shiftRows + addRoundKey
962
+ for ($i = 0; $i < $Nb; ++$i) {
963
+ $encrypt_block.=
964
+ '$'.$e.$i.' =
965
+ $sbox[ $'.$e.$i.' & 0xff] |
966
+ ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
967
+ ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
968
+ ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
969
+ }
970
+ $encrypt_block .= '$in = pack("N*"'."\n";
971
+ for ($i = 0; $i < $Nb; ++$i) {
972
+ $encrypt_block.= ',
973
+ ($'.$e.$i .' & '.((int)0xFF000000).') ^
974
+ ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^
975
+ ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^
976
+ ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^
977
+ '.$w[$i]."\n";
978
+ }
979
+ $encrypt_block .= ');';
980
+
981
+ // Generating decrypt code:
982
+ $init_decrypt.= '
983
+ static $invtables;
984
+ if (empty($invtables)) {
985
+ $invtables = &$self->_getInvTables();
986
+ }
987
+ $dt0 = $invtables[0];
988
+ $dt1 = $invtables[1];
989
+ $dt2 = $invtables[2];
990
+ $dt3 = $invtables[3];
991
+ $isbox = $invtables[4];
992
+ ';
993
+
994
+ $s = 'e';
995
+ $e = 's';
996
+ $wc = $Nb - 1;
997
+
998
+ // Preround: addRoundKey
999
+ $decrypt_block = '$in = unpack("N*", $in);'."\n";
1000
+ for ($i = 0; $i < $Nb; ++$i) {
1001
+ $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";
1002
+ }
1003
+
1004
+ // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
1005
+ for ($round = 1; $round < $Nr; ++$round) {
1006
+ list($s, $e) = array($e, $s);
1007
+ for ($i = 0; $i < $Nb; ++$i) {
1008
+ $decrypt_block.=
1009
+ '$'.$e.$i.' =
1010
+ $dt0[($'.$s.$i .' >> 24) & 0xff] ^
1011
+ $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
1012
+ $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^
1013
+ $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^
1014
+ '.$dw[++$wc].";\n";
1015
+ }
1016
+ }
1017
+
1018
+ // Finalround: subWord + shiftRows + addRoundKey
1019
+ for ($i = 0; $i < $Nb; ++$i) {
1020
+ $decrypt_block.=
1021
+ '$'.$e.$i.' =
1022
+ $isbox[ $'.$e.$i.' & 0xff] |
1023
+ ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
1024
+ ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
1025
+ ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
1026
+ }
1027
+ $decrypt_block .= '$in = pack("N*"'."\n";
1028
+ for ($i = 0; $i < $Nb; ++$i) {
1029
+ $decrypt_block.= ',
1030
+ ($'.$e.$i. ' & '.((int)0xFF000000).') ^
1031
+ ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^
1032
+ ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^
1033
+ ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^
1034
+ '.$dw[$i]."\n";
1035
+ }
1036
+ $decrypt_block .= ');';
1037
+
1038
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
1039
+ array(
1040
+ 'init_crypt' => '',
1041
+ 'init_encrypt' => $init_encrypt,
1042
+ 'init_decrypt' => $init_decrypt,
1043
+ 'encrypt_block' => $encrypt_block,
1044
+ 'decrypt_block' => $decrypt_block
1045
+ )
1046
+ );
1047
+ }
1048
+ $this->inline_crypt = $lambda_functions[$code_hash];
1049
+ }
1050
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php ADDED
@@ -0,0 +1,517 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of Triple DES.
5
+ *
6
+ * Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * Here's a short example of how to use this library:
11
+ * <code>
12
+ * <?php
13
+ * include 'Crypt/TripleDES.php';
14
+ *
15
+ * $des = new Crypt_TripleDES();
16
+ *
17
+ * $des->setKey('abcdefghijklmnopqrstuvwx');
18
+ *
19
+ * $size = 10 * 1024;
20
+ * $plaintext = '';
21
+ * for ($i = 0; $i < $size; $i++) {
22
+ * $plaintext.= 'a';
23
+ * }
24
+ *
25
+ * echo $des->decrypt($des->encrypt($plaintext));
26
+ * ?>
27
+ * </code>
28
+ *
29
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * of this software and associated documentation files (the "Software"), to deal
31
+ * in the Software without restriction, including without limitation the rights
32
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ * copies of the Software, and to permit persons to whom the Software is
34
+ * furnished to do so, subject to the following conditions:
35
+ *
36
+ * The above copyright notice and this permission notice shall be included in
37
+ * all copies or substantial portions of the Software.
38
+ *
39
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * THE SOFTWARE.
46
+ *
47
+ * @category Crypt
48
+ * @package Crypt_TripleDES
49
+ * @author Jim Wigginton <terrafrost@php.net>
50
+ * @copyright 2007 Jim Wigginton
51
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
52
+ * @link http://phpseclib.sourceforge.net
53
+ */
54
+
55
+ /**
56
+ * Include Crypt_DES
57
+ */
58
+ if (!class_exists('Crypt_DES')) {
59
+ include_once 'DES.php';
60
+ }
61
+
62
+ /**#@+
63
+ * @access public
64
+ * @see self::Crypt_TripleDES()
65
+ */
66
+ /**
67
+ * Encrypt / decrypt using inner chaining
68
+ *
69
+ * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
70
+ */
71
+ define('CRYPT_MODE_3CBC', -2);
72
+ /**
73
+ * BC version of the above.
74
+ */
75
+ define('CRYPT_DES_MODE_3CBC', -2);
76
+ /**
77
+ * Encrypt / decrypt using outer chaining
78
+ *
79
+ * Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
80
+ */
81
+ define('CRYPT_MODE_CBC3', CRYPT_MODE_CBC);
82
+ /**
83
+ * BC version of the above.
84
+ */
85
+ define('CRYPT_DES_MODE_CBC3', CRYPT_MODE_CBC3);
86
+ /**#@-*/
87
+
88
+ /**
89
+ * Pure-PHP implementation of Triple DES.
90
+ *
91
+ * @package Crypt_TripleDES
92
+ * @author Jim Wigginton <terrafrost@php.net>
93
+ * @access public
94
+ */
95
+ class Crypt_TripleDES extends Crypt_DES
96
+ {
97
+ /**
98
+ * Key Length (in bytes)
99
+ *
100
+ * @see Crypt_TripleDES::setKeyLength()
101
+ * @var int
102
+ * @access private
103
+ */
104
+ var $key_length = 24;
105
+
106
+ /**
107
+ * The default salt used by setPassword()
108
+ *
109
+ * @see Crypt_Base::password_default_salt
110
+ * @see Crypt_Base::setPassword()
111
+ * @var string
112
+ * @access private
113
+ */
114
+ var $password_default_salt = 'phpseclib';
115
+
116
+ /**
117
+ * The namespace used by the cipher for its constants.
118
+ *
119
+ * @see Crypt_DES::const_namespace
120
+ * @see Crypt_Base::const_namespace
121
+ * @var string
122
+ * @access private
123
+ */
124
+ var $const_namespace = 'DES';
125
+
126
+ /**
127
+ * The mcrypt specific name of the cipher
128
+ *
129
+ * @see Crypt_DES::cipher_name_mcrypt
130
+ * @see Crypt_Base::cipher_name_mcrypt
131
+ * @var string
132
+ * @access private
133
+ */
134
+ var $cipher_name_mcrypt = 'tripledes';
135
+
136
+ /**
137
+ * Optimizing value while CFB-encrypting
138
+ *
139
+ * @see Crypt_Base::cfb_init_len
140
+ * @var int
141
+ * @access private
142
+ */
143
+ var $cfb_init_len = 750;
144
+
145
+ /**
146
+ * max possible size of $key
147
+ *
148
+ * @see self::setKey()
149
+ * @see Crypt_DES::setKey()
150
+ * @var string
151
+ * @access private
152
+ */
153
+ var $key_length_max = 24;
154
+
155
+ /**
156
+ * Internal flag whether using CRYPT_DES_MODE_3CBC or not
157
+ *
158
+ * @var bool
159
+ * @access private
160
+ */
161
+ var $mode_3cbc;
162
+
163
+ /**
164
+ * The Crypt_DES objects
165
+ *
166
+ * Used only if $mode_3cbc === true
167
+ *
168
+ * @var array
169
+ * @access private
170
+ */
171
+ var $des;
172
+
173
+ /**
174
+ * Default Constructor.
175
+ *
176
+ * Determines whether or not the mcrypt extension should be used.
177
+ *
178
+ * $mode could be:
179
+ *
180
+ * - CRYPT_DES_MODE_ECB
181
+ *
182
+ * - CRYPT_DES_MODE_CBC
183
+ *
184
+ * - CRYPT_DES_MODE_CTR
185
+ *
186
+ * - CRYPT_DES_MODE_CFB
187
+ *
188
+ * - CRYPT_DES_MODE_OFB
189
+ *
190
+ * - CRYPT_DES_MODE_3CBC
191
+ *
192
+ * If not explicitly set, CRYPT_DES_MODE_CBC will be used.
193
+ *
194
+ * @see Crypt_DES::Crypt_DES()
195
+ * @see Crypt_Base::Crypt_Base()
196
+ * @param int $mode
197
+ * @access public
198
+ */
199
+ function __construct($mode = CRYPT_MODE_CBC)
200
+ {
201
+ switch ($mode) {
202
+ // In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
203
+ // and additional flag us internally as 3CBC
204
+ case CRYPT_DES_MODE_3CBC:
205
+ parent::Crypt_Base(CRYPT_MODE_CBC);
206
+ $this->mode_3cbc = true;
207
+
208
+ // This three $des'es will do the 3CBC work (if $key > 64bits)
209
+ $this->des = array(
210
+ new Crypt_DES(CRYPT_MODE_CBC),
211
+ new Crypt_DES(CRYPT_MODE_CBC),
212
+ new Crypt_DES(CRYPT_MODE_CBC),
213
+ );
214
+
215
+ // we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
216
+ $this->des[0]->disablePadding();
217
+ $this->des[1]->disablePadding();
218
+ $this->des[2]->disablePadding();
219
+ break;
220
+ // If not 3CBC, we init as usual
221
+ default:
222
+ parent::__construct($mode);
223
+ }
224
+ }
225
+
226
+ /**
227
+ * PHP4 compatible Default Constructor.
228
+ *
229
+ * @see self::__construct()
230
+ * @param int $mode
231
+ * @access public
232
+ */
233
+ function Crypt_TripleDES($mode = CRYPT_MODE_CBC)
234
+ {
235
+ $this->__construct($mode);
236
+ }
237
+
238
+ /**
239
+ * Test for engine validity
240
+ *
241
+ * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
242
+ *
243
+ * @see Crypt_Base::Crypt_Base()
244
+ * @param int $engine
245
+ * @access public
246
+ * @return bool
247
+ */
248
+ function isValidEngine($engine)
249
+ {
250
+ if ($engine == CRYPT_ENGINE_OPENSSL) {
251
+ $this->cipher_name_openssl_ecb = 'des-ede3';
252
+ $mode = $this->_openssl_translate_mode();
253
+ $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
254
+ }
255
+
256
+ return parent::isValidEngine($engine);
257
+ }
258
+
259
+ /**
260
+ * Sets the initialization vector. (optional)
261
+ *
262
+ * SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed
263
+ * to be all zero's.
264
+ *
265
+ * @see Crypt_Base::setIV()
266
+ * @access public
267
+ * @param string $iv
268
+ */
269
+ function setIV($iv)
270
+ {
271
+ parent::setIV($iv);
272
+ if ($this->mode_3cbc) {
273
+ $this->des[0]->setIV($iv);
274
+ $this->des[1]->setIV($iv);
275
+ $this->des[2]->setIV($iv);
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Sets the key length.
281
+ *
282
+ * Valid key lengths are 64, 128 and 192
283
+ *
284
+ * @see Crypt_Base:setKeyLength()
285
+ * @access public
286
+ * @param int $length
287
+ */
288
+ function setKeyLength($length)
289
+ {
290
+ $length >>= 3;
291
+ switch (true) {
292
+ case $length <= 8:
293
+ $this->key_length = 8;
294
+ break;
295
+ case $length <= 16:
296
+ $this->key_length = 16;
297
+ break;
298
+ default:
299
+ $this->key_length = 24;
300
+ }
301
+
302
+ parent::setKeyLength($length);
303
+ }
304
+
305
+ /**
306
+ * Sets the key.
307
+ *
308
+ * Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
309
+ * 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
310
+ *
311
+ * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
312
+ *
313
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
314
+ *
315
+ * @access public
316
+ * @see Crypt_DES::setKey()
317
+ * @see Crypt_Base::setKey()
318
+ * @param string $key
319
+ */
320
+ function setKey($key)
321
+ {
322
+ $length = $this->explicit_key_length ? $this->key_length : strlen($key);
323
+ if ($length > 8) {
324
+ $key = str_pad(substr($key, 0, 24), 24, chr(0));
325
+ // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
326
+ // http://php.net/function.mcrypt-encrypt#47973
327
+ $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
328
+ } else {
329
+ $key = str_pad($key, 8, chr(0));
330
+ }
331
+ parent::setKey($key);
332
+
333
+ // And in case of CRYPT_DES_MODE_3CBC:
334
+ // if key <= 64bits we not need the 3 $des to work,
335
+ // because we will then act as regular DES-CBC with just a <= 64bit key.
336
+ // So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
337
+ if ($this->mode_3cbc && $length > 8) {
338
+ $this->des[0]->setKey(substr($key, 0, 8));
339
+ $this->des[1]->setKey(substr($key, 8, 8));
340
+ $this->des[2]->setKey(substr($key, 16, 8));
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Encrypts a message.
346
+ *
347
+ * @see Crypt_Base::encrypt()
348
+ * @access public
349
+ * @param string $plaintext
350
+ * @return string $cipertext
351
+ */
352
+ function encrypt($plaintext)
353
+ {
354
+ // parent::en/decrypt() is able to do all the work for all modes and keylengths,
355
+ // except for: CRYPT_MODE_3CBC (inner chaining CBC) with a key > 64bits
356
+
357
+ // if the key is smaller then 8, do what we'd normally do
358
+ if ($this->mode_3cbc && strlen($this->key) > 8) {
359
+ return $this->des[2]->encrypt(
360
+ $this->des[1]->decrypt(
361
+ $this->des[0]->encrypt(
362
+ $this->_pad($plaintext)
363
+ )
364
+ )
365
+ );
366
+ }
367
+
368
+ return parent::encrypt($plaintext);
369
+ }
370
+
371
+ /**
372
+ * Decrypts a message.
373
+ *
374
+ * @see Crypt_Base::decrypt()
375
+ * @access public
376
+ * @param string $ciphertext
377
+ * @return string $plaintext
378
+ */
379
+ function decrypt($ciphertext)
380
+ {
381
+ if ($this->mode_3cbc && strlen($this->key) > 8) {
382
+ return $this->_unpad(
383
+ $this->des[0]->decrypt(
384
+ $this->des[1]->encrypt(
385
+ $this->des[2]->decrypt(
386
+ str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
387
+ )
388
+ )
389
+ )
390
+ );
391
+ }
392
+
393
+ return parent::decrypt($ciphertext);
394
+ }
395
+
396
+ /**
397
+ * Treat consecutive "packets" as if they are a continuous buffer.
398
+ *
399
+ * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
400
+ * will yield different outputs:
401
+ *
402
+ * <code>
403
+ * echo $des->encrypt(substr($plaintext, 0, 8));
404
+ * echo $des->encrypt(substr($plaintext, 8, 8));
405
+ * </code>
406
+ * <code>
407
+ * echo $des->encrypt($plaintext);
408
+ * </code>
409
+ *
410
+ * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
411
+ * another, as demonstrated with the following:
412
+ *
413
+ * <code>
414
+ * $des->encrypt(substr($plaintext, 0, 8));
415
+ * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
416
+ * </code>
417
+ * <code>
418
+ * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
419
+ * </code>
420
+ *
421
+ * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
422
+ * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
423
+ * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
424
+ *
425
+ * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
426
+ * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
427
+ * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
428
+ * however, they are also less intuitive and more likely to cause you problems.
429
+ *
430
+ * @see Crypt_Base::enableContinuousBuffer()
431
+ * @see self::disableContinuousBuffer()
432
+ * @access public
433
+ */
434
+ function enableContinuousBuffer()
435
+ {
436
+ parent::enableContinuousBuffer();
437
+ if ($this->mode_3cbc) {
438
+ $this->des[0]->enableContinuousBuffer();
439
+ $this->des[1]->enableContinuousBuffer();
440
+ $this->des[2]->enableContinuousBuffer();
441
+ }
442
+ }
443
+
444
+ /**
445
+ * Treat consecutive packets as if they are a discontinuous buffer.
446
+ *
447
+ * The default behavior.
448
+ *
449
+ * @see Crypt_Base::disableContinuousBuffer()
450
+ * @see self::enableContinuousBuffer()
451
+ * @access public
452
+ */
453
+ function disableContinuousBuffer()
454
+ {
455
+ parent::disableContinuousBuffer();
456
+ if ($this->mode_3cbc) {
457
+ $this->des[0]->disableContinuousBuffer();
458
+ $this->des[1]->disableContinuousBuffer();
459
+ $this->des[2]->disableContinuousBuffer();
460
+ }
461
+ }
462
+
463
+ /**
464
+ * Creates the key schedule
465
+ *
466
+ * @see Crypt_DES::_setupKey()
467
+ * @see Crypt_Base::_setupKey()
468
+ * @access private
469
+ */
470
+ function _setupKey()
471
+ {
472
+ switch (true) {
473
+ // if $key <= 64bits we configure our internal pure-php cipher engine
474
+ // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
475
+ case strlen($this->key) <= 8:
476
+ $this->des_rounds = 1;
477
+ break;
478
+
479
+ // otherwise, if $key > 64bits, we configure our engine to work as 3DES.
480
+ default:
481
+ $this->des_rounds = 3;
482
+
483
+ // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
484
+ if ($this->mode_3cbc) {
485
+ $this->des[0]->_setupKey();
486
+ $this->des[1]->_setupKey();
487
+ $this->des[2]->_setupKey();
488
+
489
+ // because $des[0-2] will, now, do all the work we can return here
490
+ // not need unnecessary stress parent::_setupKey() with our, now unused, $key.
491
+ return;
492
+ }
493
+ }
494
+ // setup our key
495
+ parent::_setupKey();
496
+ }
497
+
498
+ /**
499
+ * Sets the internal crypt engine
500
+ *
501
+ * @see Crypt_Base::Crypt_Base()
502
+ * @see Crypt_Base::setPreferredEngine()
503
+ * @param int $engine
504
+ * @access public
505
+ * @return int
506
+ */
507
+ function setPreferredEngine($engine)
508
+ {
509
+ if ($this->mode_3cbc) {
510
+ $this->des[0]->setPreferredEngine($engine);
511
+ $this->des[1]->setPreferredEngine($engine);
512
+ $this->des[2]->setPreferredEngine($engine);
513
+ }
514
+
515
+ return parent::setPreferredEngine($engine);
516
+ }
517
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php ADDED
@@ -0,0 +1,881 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of Twofish.
5
+ *
6
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
7
+ *
8
+ * PHP versions 4 and 5
9
+ *
10
+ * Useful resources are as follows:
11
+ *
12
+ * - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
13
+ *
14
+ * Here's a short example of how to use this library:
15
+ * <code>
16
+ * <?php
17
+ * include 'Crypt/Twofish.php';
18
+ *
19
+ * $twofish = new Crypt_Twofish();
20
+ *
21
+ * $twofish->setKey('12345678901234567890123456789012');
22
+ *
23
+ * $plaintext = str_repeat('a', 1024);
24
+ *
25
+ * echo $twofish->decrypt($twofish->encrypt($plaintext));
26
+ * ?>
27
+ * </code>
28
+ *
29
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * of this software and associated documentation files (the "Software"), to deal
31
+ * in the Software without restriction, including without limitation the rights
32
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ * copies of the Software, and to permit persons to whom the Software is
34
+ * furnished to do so, subject to the following conditions:
35
+ *
36
+ * The above copyright notice and this permission notice shall be included in
37
+ * all copies or substantial portions of the Software.
38
+ *
39
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * THE SOFTWARE.
46
+ *
47
+ * @category Crypt
48
+ * @package Crypt_Twofish
49
+ * @author Jim Wigginton <terrafrost@php.net>
50
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
51
+ * @copyright 2007 Jim Wigginton
52
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
53
+ * @link http://phpseclib.sourceforge.net
54
+ */
55
+
56
+ /**
57
+ * Include Crypt_Base
58
+ *
59
+ * Base cipher class
60
+ */
61
+ if (!class_exists('Crypt_Base')) {
62
+ include_once 'Base.php';
63
+ }
64
+
65
+ /**#@+
66
+ * @access public
67
+ * @see self::encrypt()
68
+ * @see self::decrypt()
69
+ */
70
+ /**
71
+ * Encrypt / decrypt using the Counter mode.
72
+ *
73
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
74
+ *
75
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
76
+ */
77
+ define('CRYPT_TWOFISH_MODE_CTR', CRYPT_MODE_CTR);
78
+ /**
79
+ * Encrypt / decrypt using the Electronic Code Book mode.
80
+ *
81
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
82
+ */
83
+ define('CRYPT_TWOFISH_MODE_ECB', CRYPT_MODE_ECB);
84
+ /**
85
+ * Encrypt / decrypt using the Code Book Chaining mode.
86
+ *
87
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
88
+ */
89
+ define('CRYPT_TWOFISH_MODE_CBC', CRYPT_MODE_CBC);
90
+ /**
91
+ * Encrypt / decrypt using the Cipher Feedback mode.
92
+ *
93
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
94
+ */
95
+ define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
96
+ /**
97
+ * Encrypt / decrypt using the Cipher Feedback mode.
98
+ *
99
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
100
+ */
101
+ define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
102
+ /**#@-*/
103
+
104
+ /**
105
+ * Pure-PHP implementation of Twofish.
106
+ *
107
+ * @package Crypt_Twofish
108
+ * @author Jim Wigginton <terrafrost@php.net>
109
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
110
+ * @access public
111
+ */
112
+ class Crypt_Twofish extends Crypt_Base
113
+ {
114
+ /**
115
+ * The namespace used by the cipher for its constants.
116
+ *
117
+ * @see Crypt_Base::const_namespace
118
+ * @var string
119
+ * @access private
120
+ */
121
+ var $const_namespace = 'TWOFISH';
122
+
123
+ /**
124
+ * The mcrypt specific name of the cipher
125
+ *
126
+ * @see Crypt_Base::cipher_name_mcrypt
127
+ * @var string
128
+ * @access private
129
+ */
130
+ var $cipher_name_mcrypt = 'twofish';
131
+
132
+ /**
133
+ * Optimizing value while CFB-encrypting
134
+ *
135
+ * @see Crypt_Base::cfb_init_len
136
+ * @var int
137
+ * @access private
138
+ */
139
+ var $cfb_init_len = 800;
140
+
141
+ /**
142
+ * Q-Table
143
+ *
144
+ * @var array
145
+ * @access private
146
+ */
147
+ var $q0 = array(
148
+ 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
149
+ 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
150
+ 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
151
+ 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
152
+ 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
153
+ 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
154
+ 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
155
+ 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
156
+ 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
157
+ 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
158
+ 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
159
+ 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
160
+ 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
161
+ 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
162
+ 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
163
+ 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
164
+ 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
165
+ 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
166
+ 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
167
+ 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
168
+ 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
169
+ 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
170
+ 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
171
+ 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
172
+ 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
173
+ 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
174
+ 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
175
+ 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
176
+ 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
177
+ 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
178
+ 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
179
+ 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
180
+ );
181
+
182
+ /**
183
+ * Q-Table
184
+ *
185
+ * @var array
186
+ * @access private
187
+ */
188
+ var $q1 = array(
189
+ 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
190
+ 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
191
+ 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
192
+ 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
193
+ 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
194
+ 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
195
+ 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
196
+ 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
197
+ 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
198
+ 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
199
+ 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
200
+ 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
201
+ 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
202
+ 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
203
+ 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
204
+ 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
205
+ 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
206
+ 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
207
+ 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
208
+ 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
209
+ 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
210
+ 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
211
+ 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
212
+ 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
213
+ 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
214
+ 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
215
+ 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
216
+ 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
217
+ 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
218
+ 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
219
+ 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
220
+ 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
221
+ );
222
+
223
+ /**
224
+ * M-Table
225
+ *
226
+ * @var array
227
+ * @access private
228
+ */
229
+ var $m0 = array(
230
+ 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
231
+ 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
232
+ 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
233
+ 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
234
+ 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
235
+ 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
236
+ 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
237
+ 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
238
+ 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
239
+ 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
240
+ 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
241
+ 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
242
+ 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
243
+ 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
244
+ 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
245
+ 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
246
+ 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
247
+ 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
248
+ 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
249
+ 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
250
+ 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
251
+ 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
252
+ 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
253
+ 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
254
+ 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
255
+ 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
256
+ 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
257
+ 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
258
+ 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
259
+ 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
260
+ 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
261
+ 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
262
+ );
263
+
264
+ /**
265
+ * M-Table
266
+ *
267
+ * @var array
268
+ * @access private
269
+ */
270
+ var $m1 = array(
271
+ 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
272
+ 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
273
+ 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
274
+ 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
275
+ 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
276
+ 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
277
+ 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
278
+ 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
279
+ 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
280
+ 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
281
+ 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
282
+ 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
283
+ 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
284
+ 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
285
+ 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
286
+ 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
287
+ 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
288
+ 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
289
+ 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
290
+ 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
291
+ 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
292
+ 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
293
+ 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
294
+ 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
295
+ 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
296
+ 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
297
+ 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
298
+ 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
299
+ 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
300
+ 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
301
+ 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
302
+ 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
303
+ );
304
+
305
+ /**
306
+ * M-Table
307
+ *
308
+ * @var array
309
+ * @access private
310
+ */
311
+ var $m2 = array(
312
+ 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
313
+ 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
314
+ 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
315
+ 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
316
+ 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
317
+ 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
318
+ 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
319
+ 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
320
+ 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
321
+ 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
322
+ 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
323
+ 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
324
+ 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
325
+ 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
326
+ 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
327
+ 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
328
+ 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
329
+ 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
330
+ 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
331
+ 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
332
+ 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
333
+ 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
334
+ 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
335
+ 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
336
+ 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
337
+ 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
338
+ 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
339
+ 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
340
+ 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
341
+ 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
342
+ 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
343
+ 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
344
+ );
345
+
346
+ /**
347
+ * M-Table
348
+ *
349
+ * @var array
350
+ * @access private
351
+ */
352
+ var $m3 = array(
353
+ 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
354
+ 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
355
+ 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
356
+ 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
357
+ 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
358
+ 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
359
+ 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
360
+ 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
361
+ 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
362
+ 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
363
+ 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
364
+ 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
365
+ 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
366
+ 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
367
+ 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
368
+ 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
369
+ 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
370
+ 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
371
+ 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
372
+ 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
373
+ 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
374
+ 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
375
+ 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
376
+ 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
377
+ 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
378
+ 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
379
+ 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
380
+ 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
381
+ 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
382
+ 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
383
+ 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
384
+ 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
385
+ );
386
+
387
+ /**
388
+ * The Key Schedule Array
389
+ *
390
+ * @var array
391
+ * @access private
392
+ */
393
+ var $K = array();
394
+
395
+ /**
396
+ * The Key depended S-Table 0
397
+ *
398
+ * @var array
399
+ * @access private
400
+ */
401
+ var $S0 = array();
402
+
403
+ /**
404
+ * The Key depended S-Table 1
405
+ *
406
+ * @var array
407
+ * @access private
408
+ */
409
+ var $S1 = array();
410
+
411
+ /**
412
+ * The Key depended S-Table 2
413
+ *
414
+ * @var array
415
+ * @access private
416
+ */
417
+ var $S2 = array();
418
+
419
+ /**
420
+ * The Key depended S-Table 3
421
+ *
422
+ * @var array
423
+ * @access private
424
+ */
425
+ var $S3 = array();
426
+
427
+ /**
428
+ * Holds the last used key
429
+ *
430
+ * @var array
431
+ * @access private
432
+ */
433
+ var $kl;
434
+
435
+ /**
436
+ * The Key Length (in bytes)
437
+ *
438
+ * @see Crypt_Twofish::setKeyLength()
439
+ * @var int
440
+ * @access private
441
+ */
442
+ var $key_length = 16;
443
+
444
+ /**
445
+ * Sets the key length.
446
+ *
447
+ * Valid key lengths are 128, 192 or 256 bits
448
+ *
449
+ * @access public
450
+ * @param int $length
451
+ */
452
+ function setKeyLength($length)
453
+ {
454
+ switch (true) {
455
+ case $length <= 128:
456
+ $this->key_length = 16;
457
+ break;
458
+ case $length <= 192:
459
+ $this->key_length = 24;
460
+ break;
461
+ default:
462
+ $this->key_length = 32;
463
+ }
464
+
465
+ parent::setKeyLength($length);
466
+ }
467
+
468
+ /**
469
+ * Setup the key (expansion)
470
+ *
471
+ * @see Crypt_Base::_setupKey()
472
+ * @access private
473
+ */
474
+ function _setupKey()
475
+ {
476
+ if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
477
+ // already expanded
478
+ return;
479
+ }
480
+ $this->kl = array('key' => $this->key);
481
+
482
+ /* Key expanding and generating the key-depended s-boxes */
483
+ $le_longs = unpack('V*', $this->key);
484
+ $key = unpack('C*', $this->key);
485
+ $m0 = $this->m0;
486
+ $m1 = $this->m1;
487
+ $m2 = $this->m2;
488
+ $m3 = $this->m3;
489
+ $q0 = $this->q0;
490
+ $q1 = $this->q1;
491
+
492
+ $K = $S0 = $S1 = $S2 = $S3 = array();
493
+
494
+ switch (strlen($this->key)) {
495
+ case 16:
496
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
497
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
498
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
499
+ $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
500
+ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
501
+ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
502
+ $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
503
+ $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
504
+ $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
505
+ $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
506
+ $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
507
+ $B = ($B << 8) | ($B >> 24 & 0xff);
508
+ $K[] = $A+= $B;
509
+ $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
510
+ }
511
+ for ($i = 0; $i < 256; ++$i) {
512
+ $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
513
+ $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
514
+ $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
515
+ $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
516
+ }
517
+ break;
518
+ case 24:
519
+ list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
520
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
521
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
522
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
523
+ $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
524
+ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
525
+ $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
526
+ $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
527
+ $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
528
+ $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
529
+ $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
530
+ $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
531
+ $B = ($B << 8) | ($B >> 24 & 0xff);
532
+ $K[] = $A+= $B;
533
+ $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
534
+ }
535
+ for ($i = 0; $i < 256; ++$i) {
536
+ $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
537
+ $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
538
+ $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
539
+ $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
540
+ }
541
+ break;
542
+ default: // 32
543
+ list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
544
+ list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
545
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
546
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
547
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
548
+ $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
549
+ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
550
+ $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
551
+ $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
552
+ $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
553
+ $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
554
+ $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
555
+ $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
556
+ $B = ($B << 8) | ($B >> 24 & 0xff);
557
+ $K[] = $A+= $B;
558
+ $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
559
+ }
560
+ for ($i = 0; $i < 256; ++$i) {
561
+ $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
562
+ $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
563
+ $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
564
+ $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
565
+ }
566
+ }
567
+
568
+ $this->K = $K;
569
+ $this->S0 = $S0;
570
+ $this->S1 = $S1;
571
+ $this->S2 = $S2;
572
+ $this->S3 = $S3;
573
+ }
574
+
575
+ /**
576
+ * _mdsrem function using by the twofish cipher algorithm
577
+ *
578
+ * @access private
579
+ * @param string $A
580
+ * @param string $B
581
+ * @return array
582
+ */
583
+ function _mdsrem($A, $B)
584
+ {
585
+ // No gain by unrolling this loop.
586
+ for ($i = 0; $i < 8; ++$i) {
587
+ // Get most significant coefficient.
588
+ $t = 0xff & ($B >> 24);
589
+
590
+ // Shift the others up.
591
+ $B = ($B << 8) | (0xff & ($A >> 24));
592
+ $A<<= 8;
593
+
594
+ $u = $t << 1;
595
+
596
+ // Subtract the modular polynomial on overflow.
597
+ if ($t & 0x80) {
598
+ $u^= 0x14d;
599
+ }
600
+
601
+ // Remove t * (a * x^2 + 1).
602
+ $B ^= $t ^ ($u << 16);
603
+
604
+ // Form u = a*t + t/a = t*(a + 1/a).
605
+ $u^= 0x7fffffff & ($t >> 1);
606
+
607
+ // Add the modular polynomial on underflow.
608
+ if ($t & 0x01) {
609
+ $u^= 0xa6 ;
610
+ }
611
+
612
+ // Remove t * (a + 1/a) * (x^3 + x).
613
+ $B^= ($u << 24) | ($u << 8);
614
+ }
615
+
616
+ return array(
617
+ 0xff & $B >> 24,
618
+ 0xff & $B >> 16,
619
+ 0xff & $B >> 8,
620
+ 0xff & $B);
621
+ }
622
+
623
+ /**
624
+ * Encrypts a block
625
+ *
626
+ * @access private
627
+ * @param string $in
628
+ * @return string
629
+ */
630
+ function _encryptBlock($in)
631
+ {
632
+ $S0 = $this->S0;
633
+ $S1 = $this->S1;
634
+ $S2 = $this->S2;
635
+ $S3 = $this->S3;
636
+ $K = $this->K;
637
+
638
+ $in = unpack("V4", $in);
639
+ $R0 = $K[0] ^ $in[1];
640
+ $R1 = $K[1] ^ $in[2];
641
+ $R2 = $K[2] ^ $in[3];
642
+ $R3 = $K[3] ^ $in[4];
643
+
644
+ $ki = 7;
645
+ while ($ki < 39) {
646
+ $t0 = $S0[ $R0 & 0xff] ^
647
+ $S1[($R0 >> 8) & 0xff] ^
648
+ $S2[($R0 >> 16) & 0xff] ^
649
+ $S3[($R0 >> 24) & 0xff];
650
+ $t1 = $S0[($R1 >> 24) & 0xff] ^
651
+ $S1[ $R1 & 0xff] ^
652
+ $S2[($R1 >> 8) & 0xff] ^
653
+ $S3[($R1 >> 16) & 0xff];
654
+ $R2^= $t0 + $t1 + $K[++$ki];
655
+ $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
656
+ $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
657
+
658
+ $t0 = $S0[ $R2 & 0xff] ^
659
+ $S1[($R2 >> 8) & 0xff] ^
660
+ $S2[($R2 >> 16) & 0xff] ^
661
+ $S3[($R2 >> 24) & 0xff];
662
+ $t1 = $S0[($R3 >> 24) & 0xff] ^
663
+ $S1[ $R3 & 0xff] ^
664
+ $S2[($R3 >> 8) & 0xff] ^
665
+ $S3[($R3 >> 16) & 0xff];
666
+ $R0^= ($t0 + $t1 + $K[++$ki]);
667
+ $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
668
+ $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
669
+ }
670
+
671
+ // @codingStandardsIgnoreStart
672
+ return pack("V4", $K[4] ^ $R2,
673
+ $K[5] ^ $R3,
674
+ $K[6] ^ $R0,
675
+ $K[7] ^ $R1);
676
+ // @codingStandardsIgnoreEnd
677
+ }
678
+
679
+ /**
680
+ * Decrypts a block
681
+ *
682
+ * @access private
683
+ * @param string $in
684
+ * @return string
685
+ */
686
+ function _decryptBlock($in)
687
+ {
688
+ $S0 = $this->S0;
689
+ $S1 = $this->S1;
690
+ $S2 = $this->S2;
691
+ $S3 = $this->S3;
692
+ $K = $this->K;
693
+
694
+ $in = unpack("V4", $in);
695
+ $R0 = $K[4] ^ $in[1];
696
+ $R1 = $K[5] ^ $in[2];
697
+ $R2 = $K[6] ^ $in[3];
698
+ $R3 = $K[7] ^ $in[4];
699
+
700
+ $ki = 40;
701
+ while ($ki > 8) {
702
+ $t0 = $S0[$R0 & 0xff] ^
703
+ $S1[$R0 >> 8 & 0xff] ^
704
+ $S2[$R0 >> 16 & 0xff] ^
705
+ $S3[$R0 >> 24 & 0xff];
706
+ $t1 = $S0[$R1 >> 24 & 0xff] ^
707
+ $S1[$R1 & 0xff] ^
708
+ $S2[$R1 >> 8 & 0xff] ^
709
+ $S3[$R1 >> 16 & 0xff];
710
+ $R3^= $t0 + ($t1 << 1) + $K[--$ki];
711
+ $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
712
+ $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
713
+
714
+ $t0 = $S0[$R2 & 0xff] ^
715
+ $S1[$R2 >> 8 & 0xff] ^
716
+ $S2[$R2 >> 16 & 0xff] ^
717
+ $S3[$R2 >> 24 & 0xff];
718
+ $t1 = $S0[$R3 >> 24 & 0xff] ^
719
+ $S1[$R3 & 0xff] ^
720
+ $S2[$R3 >> 8 & 0xff] ^
721
+ $S3[$R3 >> 16 & 0xff];
722
+ $R1^= $t0 + ($t1 << 1) + $K[--$ki];
723
+ $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
724
+ $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
725
+ }
726
+
727
+ // @codingStandardsIgnoreStart
728
+ return pack("V4", $K[0] ^ $R2,
729
+ $K[1] ^ $R3,
730
+ $K[2] ^ $R0,
731
+ $K[3] ^ $R1);
732
+ // @codingStandardsIgnoreEnd
733
+ }
734
+
735
+ /**
736
+ * Setup the performance-optimized function for de/encrypt()
737
+ *
738
+ * @see Crypt_Base::_setupInlineCrypt()
739
+ * @access private
740
+ */
741
+ function _setupInlineCrypt()
742
+ {
743
+ $lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
744
+
745
+ // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
746
+ // (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
747
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
748
+
749
+ // Generation of a unique hash for our generated code
750
+ $code_hash = "Crypt_Twofish, {$this->mode}";
751
+ if ($gen_hi_opt_code) {
752
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
753
+ }
754
+
755
+ if (!isset($lambda_functions[$code_hash])) {
756
+ switch (true) {
757
+ case $gen_hi_opt_code:
758
+ $K = $this->K;
759
+ $init_crypt = '
760
+ static $S0, $S1, $S2, $S3;
761
+ if (!$S0) {
762
+ for ($i = 0; $i < 256; ++$i) {
763
+ $S0[] = (int)$self->S0[$i];
764
+ $S1[] = (int)$self->S1[$i];
765
+ $S2[] = (int)$self->S2[$i];
766
+ $S3[] = (int)$self->S3[$i];
767
+ }
768
+ }
769
+ ';
770
+ break;
771
+ default:
772
+ $K = array();
773
+ for ($i = 0; $i < 40; ++$i) {
774
+ $K[] = '$K_' . $i;
775
+ }
776
+ $init_crypt = '
777
+ $S0 = $self->S0;
778
+ $S1 = $self->S1;
779
+ $S2 = $self->S2;
780
+ $S3 = $self->S3;
781
+ list(' . implode(',', $K) . ') = $self->K;
782
+ ';
783
+ }
784
+
785
+ // Generating encrypt code:
786
+ $encrypt_block = '
787
+ $in = unpack("V4", $in);
788
+ $R0 = '.$K[0].' ^ $in[1];
789
+ $R1 = '.$K[1].' ^ $in[2];
790
+ $R2 = '.$K[2].' ^ $in[3];
791
+ $R3 = '.$K[3].' ^ $in[4];
792
+ ';
793
+ for ($ki = 7, $i = 0; $i < 8; ++$i) {
794
+ $encrypt_block.= '
795
+ $t0 = $S0[ $R0 & 0xff] ^
796
+ $S1[($R0 >> 8) & 0xff] ^
797
+ $S2[($R0 >> 16) & 0xff] ^
798
+ $S3[($R0 >> 24) & 0xff];
799
+ $t1 = $S0[($R1 >> 24) & 0xff] ^
800
+ $S1[ $R1 & 0xff] ^
801
+ $S2[($R1 >> 8) & 0xff] ^
802
+ $S3[($R1 >> 16) & 0xff];
803
+ $R2^= ($t0 + $t1 + '.$K[++$ki].');
804
+ $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
805
+ $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
806
+
807
+ $t0 = $S0[ $R2 & 0xff] ^
808
+ $S1[($R2 >> 8) & 0xff] ^
809
+ $S2[($R2 >> 16) & 0xff] ^
810
+ $S3[($R2 >> 24) & 0xff];
811
+ $t1 = $S0[($R3 >> 24) & 0xff] ^
812
+ $S1[ $R3 & 0xff] ^
813
+ $S2[($R3 >> 8) & 0xff] ^
814
+ $S3[($R3 >> 16) & 0xff];
815
+ $R0^= ($t0 + $t1 + '.$K[++$ki].');
816
+ $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
817
+ $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
818
+ ';
819
+ }
820
+ $encrypt_block.= '
821
+ $in = pack("V4", '.$K[4].' ^ $R2,
822
+ '.$K[5].' ^ $R3,
823
+ '.$K[6].' ^ $R0,
824
+ '.$K[7].' ^ $R1);
825
+ ';
826
+
827
+ // Generating decrypt code:
828
+ $decrypt_block = '
829
+ $in = unpack("V4", $in);
830
+ $R0 = '.$K[4].' ^ $in[1];
831
+ $R1 = '.$K[5].' ^ $in[2];
832
+ $R2 = '.$K[6].' ^ $in[3];
833
+ $R3 = '.$K[7].' ^ $in[4];
834
+ ';
835
+ for ($ki = 40, $i = 0; $i < 8; ++$i) {
836
+ $decrypt_block.= '
837
+ $t0 = $S0[$R0 & 0xff] ^
838
+ $S1[$R0 >> 8 & 0xff] ^
839
+ $S2[$R0 >> 16 & 0xff] ^
840
+ $S3[$R0 >> 24 & 0xff];
841
+ $t1 = $S0[$R1 >> 24 & 0xff] ^
842
+ $S1[$R1 & 0xff] ^
843
+ $S2[$R1 >> 8 & 0xff] ^
844
+ $S3[$R1 >> 16 & 0xff];
845
+ $R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
846
+ $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
847
+ $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
848
+
849
+ $t0 = $S0[$R2 & 0xff] ^
850
+ $S1[$R2 >> 8 & 0xff] ^
851
+ $S2[$R2 >> 16 & 0xff] ^
852
+ $S3[$R2 >> 24 & 0xff];
853
+ $t1 = $S0[$R3 >> 24 & 0xff] ^
854
+ $S1[$R3 & 0xff] ^
855
+ $S2[$R3 >> 8 & 0xff] ^
856
+ $S3[$R3 >> 16 & 0xff];
857
+ $R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
858
+ $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
859
+ $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
860
+ ';
861
+ }
862
+ $decrypt_block.= '
863
+ $in = pack("V4", '.$K[0].' ^ $R2,
864
+ '.$K[1].' ^ $R3,
865
+ '.$K[2].' ^ $R0,
866
+ '.$K[3].' ^ $R1);
867
+ ';
868
+
869
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
870
+ array(
871
+ 'init_crypt' => $init_crypt,
872
+ 'init_encrypt' => '',
873
+ 'init_decrypt' => '',
874
+ 'encrypt_block' => $encrypt_block,
875
+ 'decrypt_block' => $decrypt_block
876
+ )
877
+ );
878
+ }
879
+ $this->inline_crypt = $lambda_functions[$code_hash];
880
+ }
881
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php ADDED
@@ -0,0 +1,601 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP ANSI Decoder
5
+ *
6
+ * PHP versions 4 and 5
7
+ *
8
+ * If you call read() in Net_SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
9
+ * They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC). They tell a
10
+ * {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
11
+ * color to display them in, etc. File_ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
12
+ *
13
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ * of this software and associated documentation files (the "Software"), to deal
15
+ * in the Software without restriction, including without limitation the rights
16
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ * copies of the Software, and to permit persons to whom the Software is
18
+ * furnished to do so, subject to the following conditions:
19
+ *
20
+ * The above copyright notice and this permission notice shall be included in
21
+ * all copies or substantial portions of the Software.
22
+ *
23
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
+ * THE SOFTWARE.
30
+ *
31
+ * @category File
32
+ * @package File_ANSI
33
+ * @author Jim Wigginton <terrafrost@php.net>
34
+ * @copyright 2012 Jim Wigginton
35
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
36
+ * @link http://phpseclib.sourceforge.net
37
+ */
38
+
39
+ /**
40
+ * Pure-PHP ANSI Decoder
41
+ *
42
+ * @package File_ANSI
43
+ * @author Jim Wigginton <terrafrost@php.net>
44
+ * @access public
45
+ */
46
+ class File_ANSI
47
+ {
48
+ /**
49
+ * Max Width
50
+ *
51
+ * @var int
52
+ * @access private
53
+ */
54
+ var $max_x;
55
+
56
+ /**
57
+ * Max Height
58
+ *
59
+ * @var int
60
+ * @access private
61
+ */
62
+ var $max_y;
63
+
64
+ /**
65
+ * Max History
66
+ *
67
+ * @var int
68
+ * @access private
69
+ */
70
+ var $max_history;
71
+
72
+ /**
73
+ * History
74
+ *
75
+ * @var array
76
+ * @access private
77
+ */
78
+ var $history;
79
+
80
+ /**
81
+ * History Attributes
82
+ *
83
+ * @var array
84
+ * @access private
85
+ */
86
+ var $history_attrs;
87
+
88
+ /**
89
+ * Current Column
90
+ *
91
+ * @var int
92
+ * @access private
93
+ */
94
+ var $x;
95
+
96
+ /**
97
+ * Current Row
98
+ *
99
+ * @var int
100
+ * @access private
101
+ */
102
+ var $y;
103
+
104
+ /**
105
+ * Old Column
106
+ *
107
+ * @var int
108
+ * @access private
109
+ */
110
+ var $old_x;
111
+
112
+ /**
113
+ * Old Row
114
+ *
115
+ * @var int
116
+ * @access private
117
+ */
118
+ var $old_y;
119
+
120
+ /**
121
+ * An empty attribute cell
122
+ *
123
+ * @var object
124
+ * @access private
125
+ */
126
+ var $base_attr_cell;
127
+
128
+ /**
129
+ * The current attribute cell
130
+ *
131
+ * @var object
132
+ * @access private
133
+ */
134
+ var $attr_cell;
135
+
136
+ /**
137
+ * An empty attribute row
138
+ *
139
+ * @var array
140
+ * @access private
141
+ */
142
+ var $attr_row;
143
+
144
+ /**
145
+ * The current screen text
146
+ *
147
+ * @var array
148
+ * @access private
149
+ */
150
+ var $screen;
151
+
152
+ /**
153
+ * The current screen attributes
154
+ *
155
+ * @var array
156
+ * @access private
157
+ */
158
+ var $attrs;
159
+
160
+ /**
161
+ * Current ANSI code
162
+ *
163
+ * @var string
164
+ * @access private
165
+ */
166
+ var $ansi;
167
+
168
+ /**
169
+ * Tokenization
170
+ *
171
+ * @var array
172
+ * @access private
173
+ */
174
+ var $tokenization;
175
+
176
+ /**
177
+ * Default Constructor.
178
+ *
179
+ * @return File_ANSI
180
+ * @access public
181
+ */
182
+ function __construct()
183
+ {
184
+ $attr_cell = new stdClass();
185
+ $attr_cell->bold = false;
186
+ $attr_cell->underline = false;
187
+ $attr_cell->blink = false;
188
+ $attr_cell->background = 'black';
189
+ $attr_cell->foreground = 'white';
190
+ $attr_cell->reverse = false;
191
+ $this->base_attr_cell = clone($attr_cell);
192
+ $this->attr_cell = clone($attr_cell);
193
+
194
+ $this->setHistory(200);
195
+ $this->setDimensions(80, 24);
196
+ }
197
+
198
+ /**
199
+ * PHP4 compatible Default Constructor.
200
+ *
201
+ * @see self::__construct()
202
+ * @access public
203
+ */
204
+ function File_ANSI()
205
+ {
206
+ $this->__construct($mode);
207
+ }
208
+
209
+ /**
210
+ * Set terminal width and height
211
+ *
212
+ * Resets the screen as well
213
+ *
214
+ * @param int $x
215
+ * @param int $y
216
+ * @access public
217
+ */
218
+ function setDimensions($x, $y)
219
+ {
220
+ $this->max_x = $x - 1;
221
+ $this->max_y = $y - 1;
222
+ $this->x = $this->y = 0;
223
+ $this->history = $this->history_attrs = array();
224
+ $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
225
+ $this->screen = array_fill(0, $this->max_y + 1, '');
226
+ $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
227
+ $this->ansi = '';
228
+ }
229
+
230
+ /**
231
+ * Set the number of lines that should be logged past the terminal height
232
+ *
233
+ * @param int $x
234
+ * @param int $y
235
+ * @access public
236
+ */
237
+ function setHistory($history)
238
+ {
239
+ $this->max_history = $history;
240
+ }
241
+
242
+ /**
243
+ * Load a string
244
+ *
245
+ * @param string $source
246
+ * @access public
247
+ */
248
+ function loadString($source)
249
+ {
250
+ $this->setDimensions($this->max_x + 1, $this->max_y + 1);
251
+ $this->appendString($source);
252
+ }
253
+
254
+ /**
255
+ * Appdend a string
256
+ *
257
+ * @param string $source
258
+ * @access public
259
+ */
260
+ function appendString($source)
261
+ {
262
+ $this->tokenization = array('');
263
+ for ($i = 0; $i < strlen($source); $i++) {
264
+ if (strlen($this->ansi)) {
265
+ $this->ansi.= $source[$i];
266
+ $chr = ord($source[$i]);
267
+ // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
268
+ // single character CSI's not currently supported
269
+ switch (true) {
270
+ case $this->ansi == "\x1B=":
271
+ $this->ansi = '';
272
+ continue 2;
273
+ case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
274
+ case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
275
+ break;
276
+ default:
277
+ continue 2;
278
+ }
279
+ $this->tokenization[] = $this->ansi;
280
+ $this->tokenization[] = '';
281
+ // http://ascii-table.com/ansi-escape-sequences-vt-100.php
282
+ switch ($this->ansi) {
283
+ case "\x1B[H": // Move cursor to upper left corner
284
+ $this->old_x = $this->x;
285
+ $this->old_y = $this->y;
286
+ $this->x = $this->y = 0;
287
+ break;
288
+ case "\x1B[J": // Clear screen from cursor down
289
+ $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
290
+ $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
291
+
292
+ $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
293
+ $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
294
+
295
+ if (count($this->history) == $this->max_history) {
296
+ array_shift($this->history);
297
+ array_shift($this->history_attrs);
298
+ }
299
+ case "\x1B[K": // Clear screen from cursor right
300
+ $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
301
+
302
+ array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell));
303
+ break;
304
+ case "\x1B[2K": // Clear entire line
305
+ $this->screen[$this->y] = str_repeat(' ', $this->x);
306
+ $this->attrs[$this->y] = $this->attr_row;
307
+ break;
308
+ case "\x1B[?1h": // set cursor key to application
309
+ case "\x1B[?25h": // show the cursor
310
+ case "\x1B(B": // set united states g0 character set
311
+ break;
312
+ case "\x1BE": // Move to next line
313
+ $this->_newLine();
314
+ $this->x = 0;
315
+ break;
316
+ default:
317
+ switch (true) {
318
+ case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines
319
+ $this->old_y = $this->y;
320
+ $this->y+= $match[1];
321
+ break;
322
+ case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
323
+ $this->old_x = $this->x;
324
+ $this->old_y = $this->y;
325
+ $this->x = $match[2] - 1;
326
+ $this->y = $match[1] - 1;
327
+ break;
328
+ case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
329
+ $this->old_x = $this->x;
330
+ $this->x+= $match[1];
331
+ break;
332
+ case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
333
+ $this->old_x = $this->x;
334
+ $this->x-= $match[1];
335
+ break;
336
+ case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
337
+ break;
338
+ case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
339
+ $attr_cell = &$this->attr_cell;
340
+ $mods = explode(';', $match[1]);
341
+ foreach ($mods as $mod) {
342
+ switch ($mod) {
343
+ case 0: // Turn off character attributes
344
+ $attr_cell = clone($this->base_attr_cell);
345
+ break;
346
+ case 1: // Turn bold mode on
347
+ $attr_cell->bold = true;
348
+ break;
349
+ case 4: // Turn underline mode on
350
+ $attr_cell->underline = true;
351
+ break;
352
+ case 5: // Turn blinking mode on
353
+ $attr_cell->blink = true;
354
+ break;
355
+ case 7: // Turn reverse video on
356
+ $attr_cell->reverse = !$attr_cell->reverse;
357
+ $temp = $attr_cell->background;
358
+ $attr_cell->background = $attr_cell->foreground;
359
+ $attr_cell->foreground = $temp;
360
+ break;
361
+ default: // set colors
362
+ //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
363
+ $front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' };
364
+ //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
365
+ $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
366
+ switch ($mod) {
367
+ // @codingStandardsIgnoreStart
368
+ case 30: $front = 'black'; break;
369
+ case 31: $front = 'red'; break;
370
+ case 32: $front = 'green'; break;
371
+ case 33: $front = 'yellow'; break;
372
+ case 34: $front = 'blue'; break;
373
+ case 35: $front = 'magenta'; break;
374
+ case 36: $front = 'cyan'; break;
375
+ case 37: $front = 'white'; break;
376
+
377
+ case 40: $back = 'black'; break;
378
+ case 41: $back = 'red'; break;
379
+ case 42: $back = 'green'; break;
380
+ case 43: $back = 'yellow'; break;
381
+ case 44: $back = 'blue'; break;
382
+ case 45: $back = 'magenta'; break;
383
+ case 46: $back = 'cyan'; break;
384
+ case 47: $back = 'white'; break;
385
+ // @codingStandardsIgnoreEnd
386
+
387
+ default:
388
+ //user_error('Unsupported attribute: ' . $mod);
389
+ $this->ansi = '';
390
+ break 2;
391
+ }
392
+ }
393
+ }
394
+ break;
395
+ default:
396
+ //user_error("{$this->ansi} is unsupported\r\n");
397
+ }
398
+ }
399
+ $this->ansi = '';
400
+ continue;
401
+ }
402
+
403
+ $this->tokenization[count($this->tokenization) - 1].= $source[$i];
404
+ switch ($source[$i]) {
405
+ case "\r":
406
+ $this->x = 0;
407
+ break;
408
+ case "\n":
409
+ $this->_newLine();
410
+ break;
411
+ case "\x08": // backspace
412
+ if ($this->x) {
413
+ $this->x--;
414
+ $this->attrs[$this->y][$this->x] = clone($this->base_attr_cell);
415
+ $this->screen[$this->y] = substr_replace(
416
+ $this->screen[$this->y],
417
+ $source[$i],
418
+ $this->x,
419
+ 1
420
+ );
421
+ }
422
+ break;
423
+ case "\x0F": // shift
424
+ break;
425
+ case "\x1B": // start ANSI escape code
426
+ $this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
427
+ //if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
428
+ // array_pop($this->tokenization);
429
+ //}
430
+ $this->ansi.= "\x1B";
431
+ break;
432
+ default:
433
+ $this->attrs[$this->y][$this->x] = clone($this->attr_cell);
434
+ if ($this->x > strlen($this->screen[$this->y])) {
435
+ $this->screen[$this->y] = str_repeat(' ', $this->x);
436
+ }
437
+ $this->screen[$this->y] = substr_replace(
438
+ $this->screen[$this->y],
439
+ $source[$i],
440
+ $this->x,
441
+ 1
442
+ );
443
+
444
+ if ($this->x > $this->max_x) {
445
+ $this->x = 0;
446
+ $this->y++;
447
+ } else {
448
+ $this->x++;
449
+ }
450
+ }
451
+ }
452
+ }
453
+
454
+ /**
455
+ * Add a new line
456
+ *
457
+ * Also update the $this->screen and $this->history buffers
458
+ *
459
+ * @access private
460
+ */
461
+ function _newLine()
462
+ {
463
+ //if ($this->y < $this->max_y) {
464
+ // $this->y++;
465
+ //}
466
+
467
+ while ($this->y >= $this->max_y) {
468
+ $this->history = array_merge($this->history, array(array_shift($this->screen)));
469
+ $this->screen[] = '';
470
+
471
+ $this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
472
+ $this->attrs[] = $this->attr_row;
473
+
474
+ if (count($this->history) >= $this->max_history) {
475
+ array_shift($this->history);
476
+ array_shift($this->history_attrs);
477
+ }
478
+
479
+ $this->y--;
480
+ }
481
+ $this->y++;
482
+ }
483
+
484
+ /**
485
+ * Returns the current coordinate without preformating
486
+ *
487
+ * @access private
488
+ * @return string
489
+ */
490
+ function _processCoordinate($last_attr, $cur_attr, $char)
491
+ {
492
+ $output = '';
493
+
494
+ if ($last_attr != $cur_attr) {
495
+ $close = $open = '';
496
+ if ($last_attr->foreground != $cur_attr->foreground) {
497
+ if ($cur_attr->foreground != 'white') {
498
+ $open.= '<span style="color: ' . $cur_attr->foreground . '">';
499
+ }
500
+ if ($last_attr->foreground != 'white') {
501
+ $close = '</span>' . $close;
502
+ }
503
+ }
504
+ if ($last_attr->background != $cur_attr->background) {
505
+ if ($cur_attr->background != 'black') {
506
+ $open.= '<span style="background: ' . $cur_attr->background . '">';
507
+ }
508
+ if ($last_attr->background != 'black') {
509
+ $close = '</span>' . $close;
510
+ }
511
+ }
512
+ if ($last_attr->bold != $cur_attr->bold) {
513
+ if ($cur_attr->bold) {
514
+ $open.= '<b>';
515
+ } else {
516
+ $close = '</b>' . $close;
517
+ }
518
+ }
519
+ if ($last_attr->underline != $cur_attr->underline) {
520
+ if ($cur_attr->underline) {
521
+ $open.= '<u>';
522
+ } else {
523
+ $close = '</u>' . $close;
524
+ }
525
+ }
526
+ if ($last_attr->blink != $cur_attr->blink) {
527
+ if ($cur_attr->blink) {
528
+ $open.= '<blink>';
529
+ } else {
530
+ $close = '</blink>' . $close;
531
+ }
532
+ }
533
+ $output.= $close . $open;
534
+ }
535
+
536
+ $output.= htmlspecialchars($char);
537
+
538
+ return $output;
539
+ }
540
+
541
+ /**
542
+ * Returns the current screen without preformating
543
+ *
544
+ * @access private
545
+ * @return string
546
+ */
547
+ function _getScreen()
548
+ {
549
+ $output = '';
550
+ $last_attr = $this->base_attr_cell;
551
+ for ($i = 0; $i <= $this->max_y; $i++) {
552
+ for ($j = 0; $j <= $this->max_x; $j++) {
553
+ $cur_attr = $this->attrs[$i][$j];
554
+ $output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
555
+ $last_attr = $this->attrs[$i][$j];
556
+ }
557
+ $output.= "\r\n";
558
+ }
559
+ $output = substr($output, 0, -2);
560
+ // close any remaining open tags
561
+ $output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, '');
562
+ return rtrim($output);
563
+ }
564
+
565
+ /**
566
+ * Returns the current screen
567
+ *
568
+ * @access public
569
+ * @return string
570
+ */
571
+ function getScreen()
572
+ {
573
+ return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->_getScreen() . '</pre>';
574
+ }
575
+
576
+ /**
577
+ * Returns the current screen and the x previous lines
578
+ *
579
+ * @access public
580
+ * @return string
581
+ */
582
+ function getHistory()
583
+ {
584
+ $scrollback = '';
585
+ $last_attr = $this->base_attr_cell;
586
+ for ($i = 0; $i < count($this->history); $i++) {
587
+ for ($j = 0; $j <= $this->max_x + 1; $j++) {
588
+ $cur_attr = $this->history_attrs[$i][$j];
589
+ $scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
590
+ $last_attr = $this->history_attrs[$i][$j];
591
+ }
592
+ $scrollback.= "\r\n";
593
+ }
594
+ $base_attr_cell = $this->base_attr_cell;
595
+ $this->base_attr_cell = $last_attr;
596
+ $scrollback.= $this->_getScreen();
597
+ $this->base_attr_cell = $base_attr_cell;
598
+
599
+ return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
600
+ }
601
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php ADDED
@@ -0,0 +1,1407 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP ASN.1 Parser
5
+ *
6
+ * PHP versions 4 and 5
7
+ *
8
+ * ASN.1 provides the semantics for data encoded using various schemes. The most commonly
9
+ * utilized scheme is DER or the "Distinguished Encoding Rules". PEM's are base64 encoded
10
+ * DER blobs.
11
+ *
12
+ * File_ASN1 decodes and encodes DER formatted messages and places them in a semantic context.
13
+ *
14
+ * Uses the 1988 ASN.1 syntax.
15
+ *
16
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
17
+ * of this software and associated documentation files (the "Software"), to deal
18
+ * in the Software without restriction, including without limitation the rights
19
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
+ * copies of the Software, and to permit persons to whom the Software is
21
+ * furnished to do so, subject to the following conditions:
22
+ *
23
+ * The above copyright notice and this permission notice shall be included in
24
+ * all copies or substantial portions of the Software.
25
+ *
26
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
+ * THE SOFTWARE.
33
+ *
34
+ * @category File
35
+ * @package File_ASN1
36
+ * @author Jim Wigginton <terrafrost@php.net>
37
+ * @copyright 2012 Jim Wigginton
38
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
39
+ * @link http://phpseclib.sourceforge.net
40
+ */
41
+
42
+ /**#@+
43
+ * Tag Classes
44
+ *
45
+ * @access private
46
+ * @link http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12
47
+ */
48
+ define('FILE_ASN1_CLASS_UNIVERSAL', 0);
49
+ define('FILE_ASN1_CLASS_APPLICATION', 1);
50
+ define('FILE_ASN1_CLASS_CONTEXT_SPECIFIC', 2);
51
+ define('FILE_ASN1_CLASS_PRIVATE', 3);
52
+ /**#@-*/
53
+
54
+ /**#@+
55
+ * Tag Classes
56
+ *
57
+ * @access private
58
+ * @link http://www.obj-sys.com/asn1tutorial/node124.html
59
+ */
60
+ define('FILE_ASN1_TYPE_BOOLEAN', 1);
61
+ define('FILE_ASN1_TYPE_INTEGER', 2);
62
+ define('FILE_ASN1_TYPE_BIT_STRING', 3);
63
+ define('FILE_ASN1_TYPE_OCTET_STRING', 4);
64
+ define('FILE_ASN1_TYPE_NULL', 5);
65
+ define('FILE_ASN1_TYPE_OBJECT_IDENTIFIER', 6);
66
+ //define('FILE_ASN1_TYPE_OBJECT_DESCRIPTOR', 7);
67
+ //define('FILE_ASN1_TYPE_INSTANCE_OF', 8); // EXTERNAL
68
+ define('FILE_ASN1_TYPE_REAL', 9);
69
+ define('FILE_ASN1_TYPE_ENUMERATED', 10);
70
+ //define('FILE_ASN1_TYPE_EMBEDDED', 11);
71
+ define('FILE_ASN1_TYPE_UTF8_STRING', 12);
72
+ //define('FILE_ASN1_TYPE_RELATIVE_OID', 13);
73
+ define('FILE_ASN1_TYPE_SEQUENCE', 16); // SEQUENCE OF
74
+ define('FILE_ASN1_TYPE_SET', 17); // SET OF
75
+ /**#@-*/
76
+ /**#@+
77
+ * More Tag Classes
78
+ *
79
+ * @access private
80
+ * @link http://www.obj-sys.com/asn1tutorial/node10.html
81
+ */
82
+ define('FILE_ASN1_TYPE_NUMERIC_STRING', 18);
83
+ define('FILE_ASN1_TYPE_PRINTABLE_STRING', 19);
84
+ define('FILE_ASN1_TYPE_TELETEX_STRING', 20); // T61String
85
+ define('FILE_ASN1_TYPE_VIDEOTEX_STRING', 21);
86
+ define('FILE_ASN1_TYPE_IA5_STRING', 22);
87
+ define('FILE_ASN1_TYPE_UTC_TIME', 23);
88
+ define('FILE_ASN1_TYPE_GENERALIZED_TIME', 24);
89
+ define('FILE_ASN1_TYPE_GRAPHIC_STRING', 25);
90
+ define('FILE_ASN1_TYPE_VISIBLE_STRING', 26); // ISO646String
91
+ define('FILE_ASN1_TYPE_GENERAL_STRING', 27);
92
+ define('FILE_ASN1_TYPE_UNIVERSAL_STRING', 28);
93
+ //define('FILE_ASN1_TYPE_CHARACTER_STRING', 29);
94
+ define('FILE_ASN1_TYPE_BMP_STRING', 30);
95
+ /**#@-*/
96
+
97
+ /**#@+
98
+ * Tag Aliases
99
+ *
100
+ * These tags are kinda place holders for other tags.
101
+ *
102
+ * @access private
103
+ */
104
+ define('FILE_ASN1_TYPE_CHOICE', -1);
105
+ define('FILE_ASN1_TYPE_ANY', -2);
106
+ /**#@-*/
107
+
108
+ /**
109
+ * ASN.1 Element
110
+ *
111
+ * Bypass normal encoding rules in File_ASN1::encodeDER()
112
+ *
113
+ * @package File_ASN1
114
+ * @author Jim Wigginton <terrafrost@php.net>
115
+ * @access public
116
+ */
117
+ class File_ASN1_Element
118
+ {
119
+ /**
120
+ * Raw element value
121
+ *
122
+ * @var string
123
+ * @access private
124
+ */
125
+ var $element;
126
+
127
+ /**
128
+ * Constructor
129
+ *
130
+ * @param string $encoded
131
+ * @return File_ASN1_Element
132
+ * @access public
133
+ */
134
+ function __construct($encoded)
135
+ {
136
+ $this->element = $encoded;
137
+ }
138
+
139
+ /**
140
+ * PHP4 compatible Default Constructor.
141
+ *
142
+ * @see self::__construct()
143
+ * @param int $mode
144
+ * @access public
145
+ */
146
+ function File_ASN1_Element($encoded)
147
+ {
148
+ $this->__construct($encoded);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Pure-PHP ASN.1 Parser
154
+ *
155
+ * @package File_ASN1
156
+ * @author Jim Wigginton <terrafrost@php.net>
157
+ * @access public
158
+ */
159
+ class File_ASN1
160
+ {
161
+ /**
162
+ * ASN.1 object identifier
163
+ *
164
+ * @var array
165
+ * @access private
166
+ * @link http://en.wikipedia.org/wiki/Object_identifier
167
+ */
168
+ var $oids = array();
169
+
170
+ /**
171
+ * Default date format
172
+ *
173
+ * @var string
174
+ * @access private
175
+ * @link http://php.net/class.datetime
176
+ */
177
+ var $format = 'D, d M Y H:i:s O';
178
+
179
+ /**
180
+ * Default date format
181
+ *
182
+ * @var array
183
+ * @access private
184
+ * @see self::setTimeFormat()
185
+ * @see self::asn1map()
186
+ * @link http://php.net/class.datetime
187
+ */
188
+ var $encoded;
189
+
190
+ /**
191
+ * Filters
192
+ *
193
+ * If the mapping type is FILE_ASN1_TYPE_ANY what do we actually encode it as?
194
+ *
195
+ * @var array
196
+ * @access private
197
+ * @see self::_encode_der()
198
+ */
199
+ var $filters;
200
+
201
+ /**
202
+ * Type mapping table for the ANY type.
203
+ *
204
+ * Structured or unknown types are mapped to a FILE_ASN1_Element.
205
+ * Unambiguous types get the direct mapping (int/real/bool).
206
+ * Others are mapped as a choice, with an extra indexing level.
207
+ *
208
+ * @var array
209
+ * @access public
210
+ */
211
+ var $ANYmap = array(
212
+ FILE_ASN1_TYPE_BOOLEAN => true,
213
+ FILE_ASN1_TYPE_INTEGER => true,
214
+ FILE_ASN1_TYPE_BIT_STRING => 'bitString',
215
+ FILE_ASN1_TYPE_OCTET_STRING => 'octetString',
216
+ FILE_ASN1_TYPE_NULL => 'null',
217
+ FILE_ASN1_TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
218
+ FILE_ASN1_TYPE_REAL => true,
219
+ FILE_ASN1_TYPE_ENUMERATED => 'enumerated',
220
+ FILE_ASN1_TYPE_UTF8_STRING => 'utf8String',
221
+ FILE_ASN1_TYPE_NUMERIC_STRING => 'numericString',
222
+ FILE_ASN1_TYPE_PRINTABLE_STRING => 'printableString',
223
+ FILE_ASN1_TYPE_TELETEX_STRING => 'teletexString',
224
+ FILE_ASN1_TYPE_VIDEOTEX_STRING => 'videotexString',
225
+ FILE_ASN1_TYPE_IA5_STRING => 'ia5String',
226
+ FILE_ASN1_TYPE_UTC_TIME => 'utcTime',
227
+ FILE_ASN1_TYPE_GENERALIZED_TIME => 'generalTime',
228
+ FILE_ASN1_TYPE_GRAPHIC_STRING => 'graphicString',
229
+ FILE_ASN1_TYPE_VISIBLE_STRING => 'visibleString',
230
+ FILE_ASN1_TYPE_GENERAL_STRING => 'generalString',
231
+ FILE_ASN1_TYPE_UNIVERSAL_STRING => 'universalString',
232
+ //FILE_ASN1_TYPE_CHARACTER_STRING => 'characterString',
233
+ FILE_ASN1_TYPE_BMP_STRING => 'bmpString'
234
+ );
235
+
236
+ /**
237
+ * String type to character size mapping table.
238
+ *
239
+ * Non-convertable types are absent from this table.
240
+ * size == 0 indicates variable length encoding.
241
+ *
242
+ * @var array
243
+ * @access public
244
+ */
245
+ var $stringTypeSize = array(
246
+ FILE_ASN1_TYPE_UTF8_STRING => 0,
247
+ FILE_ASN1_TYPE_BMP_STRING => 2,
248
+ FILE_ASN1_TYPE_UNIVERSAL_STRING => 4,
249
+ FILE_ASN1_TYPE_PRINTABLE_STRING => 1,
250
+ FILE_ASN1_TYPE_TELETEX_STRING => 1,
251
+ FILE_ASN1_TYPE_IA5_STRING => 1,
252
+ FILE_ASN1_TYPE_VISIBLE_STRING => 1,
253
+ );
254
+
255
+ /**
256
+ * Default Constructor.
257
+ *
258
+ * @access public
259
+ */
260
+ function __construct()
261
+ {
262
+ static $static_init = null;
263
+ if (!$static_init) {
264
+ $static_init = true;
265
+ if (!class_exists('Math_BigInteger')) {
266
+ include_once 'Math/BigInteger.php';
267
+ }
268
+ }
269
+ }
270
+
271
+ /**
272
+ * PHP4 compatible Default Constructor.
273
+ *
274
+ * @see self::__construct()
275
+ * @access public
276
+ */
277
+ function File_ASN1()
278
+ {
279
+ $this->__construct($mode);
280
+ }
281
+
282
+ /**
283
+ * Parse BER-encoding
284
+ *
285
+ * Serves a similar purpose to openssl's asn1parse
286
+ *
287
+ * @param string $encoded
288
+ * @return array
289
+ * @access public
290
+ */
291
+ function decodeBER($encoded)
292
+ {
293
+ if (is_object($encoded) && strtolower(get_class($encoded)) == 'file_asn1_element') {
294
+ $encoded = $encoded->element;
295
+ }
296
+
297
+ $this->encoded = $encoded;
298
+ // encapsulate in an array for BC with the old decodeBER
299
+ return array($this->_decode_ber($encoded));
300
+ }
301
+
302
+ /**
303
+ * Parse BER-encoding (Helper function)
304
+ *
305
+ * Sometimes we want to get the BER encoding of a particular tag. $start lets us do that without having to reencode.
306
+ * $encoded is passed by reference for the recursive calls done for FILE_ASN1_TYPE_BIT_STRING and
307
+ * FILE_ASN1_TYPE_OCTET_STRING. In those cases, the indefinite length is used.
308
+ *
309
+ * @param string $encoded
310
+ * @param int $start
311
+ * @param int $encoded_pos
312
+ * @return array
313
+ * @access private
314
+ */
315
+ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
316
+ {
317
+ $current = array('start' => $start);
318
+
319
+ $type = ord($encoded[$encoded_pos++]);
320
+ $start++;
321
+
322
+ $constructed = ($type >> 5) & 1;
323
+
324
+ $tag = $type & 0x1F;
325
+ if ($tag == 0x1F) {
326
+ $tag = 0;
327
+ // process septets (since the eighth bit is ignored, it's not an octet)
328
+ do {
329
+ $loop = ord($encoded[0]) >> 7;
330
+ $tag <<= 7;
331
+ $tag |= ord($encoded[$encoded_pos++]) & 0x7F;
332
+ $start++;
333
+ } while ($loop);
334
+ }
335
+
336
+ // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
337
+ $length = ord($encoded[$encoded_pos++]);
338
+ $start++;
339
+ if ($length == 0x80) { // indefinite length
340
+ // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
341
+ // immediately available." -- paragraph 8.1.3.2.c
342
+ $length = strlen($encoded) - $encoded_pos;
343
+ } elseif ($length & 0x80) { // definite length, long form
344
+ // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
345
+ // support it up to four.
346
+ $length&= 0x7F;
347
+ $temp = substr($encoded, $encoded_pos, $length);
348
+ $encoded_pos += $length;
349
+ // tags of indefinte length don't really have a header length; this length includes the tag
350
+ $current+= array('headerlength' => $length + 2);
351
+ $start+= $length;
352
+ extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
353
+ } else {
354
+ $current+= array('headerlength' => 2);
355
+ }
356
+
357
+ if ($length > (strlen($encoded) - $encoded_pos)) {
358
+ return false;
359
+ }
360
+
361
+ $content = substr($encoded, $encoded_pos, $length);
362
+ $content_pos = 0;
363
+
364
+ // at this point $length can be overwritten. it's only accurate for definite length things as is
365
+
366
+ /* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
367
+ built-in types. It defines an application-independent data type that must be distinguishable from all other
368
+ data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
369
+ have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within
370
+ a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the
371
+ alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this
372
+ data type; the term CONTEXT-SPECIFIC does not appear.
373
+
374
+ -- http://www.obj-sys.com/asn1tutorial/node12.html */
375
+ $class = ($type >> 6) & 3;
376
+ switch ($class) {
377
+ case FILE_ASN1_CLASS_APPLICATION:
378
+ case FILE_ASN1_CLASS_PRIVATE:
379
+ case FILE_ASN1_CLASS_CONTEXT_SPECIFIC:
380
+ if (!$constructed) {
381
+ return array(
382
+ 'type' => $class,
383
+ 'constant' => $tag,
384
+ 'content' => $content,
385
+ 'length' => $length + $start - $current['start']
386
+ );
387
+ }
388
+
389
+ $newcontent = array();
390
+ $remainingLength = $length;
391
+ while ($remainingLength > 0) {
392
+ $temp = $this->_decode_ber($content, $start, $content_pos);
393
+ $length = $temp['length'];
394
+ // end-of-content octets - see paragraph 8.1.5
395
+ if (substr($content, $content_pos + $length, 2) == "\0\0") {
396
+ $length+= 2;
397
+ $start+= $length;
398
+ $newcontent[] = $temp;
399
+ break;
400
+ }
401
+ $start+= $length;
402
+ $remainingLength-= $length;
403
+ $newcontent[] = $temp;
404
+ $content_pos += $length;
405
+ }
406
+
407
+ return array(
408
+ 'type' => $class,
409
+ 'constant' => $tag,
410
+ // the array encapsulation is for BC with the old format
411
+ 'content' => $newcontent,
412
+ // the only time when $content['headerlength'] isn't defined is when the length is indefinite.
413
+ // the absence of $content['headerlength'] is how we know if something is indefinite or not.
414
+ // technically, it could be defined to be 2 and then another indicator could be used but whatever.
415
+ 'length' => $start - $current['start']
416
+ ) + $current;
417
+ }
418
+
419
+ $current+= array('type' => $tag);
420
+
421
+ // decode UNIVERSAL tags
422
+ switch ($tag) {
423
+ case FILE_ASN1_TYPE_BOOLEAN:
424
+ // "The contents octets shall consist of a single octet." -- paragraph 8.2.1
425
+ //if (strlen($content) != 1) {
426
+ // return false;
427
+ //}
428
+ $current['content'] = (bool) ord($content[$content_pos]);
429
+ break;
430
+ case FILE_ASN1_TYPE_INTEGER:
431
+ case FILE_ASN1_TYPE_ENUMERATED:
432
+ $current['content'] = new Math_BigInteger(substr($content, $content_pos), -256);
433
+ break;
434
+ case FILE_ASN1_TYPE_REAL: // not currently supported
435
+ return false;
436
+ case FILE_ASN1_TYPE_BIT_STRING:
437
+ // The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
438
+ // the number of unused bits in the final subsequent octet. The number shall be in the range zero to
439
+ // seven.
440
+ if (!$constructed) {
441
+ $current['content'] = substr($content, $content_pos);
442
+ } else {
443
+ $temp = $this->_decode_ber($content, $start, $content_pos);
444
+ $length-= (strlen($content) - $content_pos);
445
+ $last = count($temp) - 1;
446
+ for ($i = 0; $i < $last; $i++) {
447
+ // all subtags should be bit strings
448
+ //if ($temp[$i]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
449
+ // return false;
450
+ //}
451
+ $current['content'].= substr($temp[$i]['content'], 1);
452
+ }
453
+ // all subtags should be bit strings
454
+ //if ($temp[$last]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
455
+ // return false;
456
+ //}
457
+ $current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
458
+ }
459
+ break;
460
+ case FILE_ASN1_TYPE_OCTET_STRING:
461
+ if (!$constructed) {
462
+ $current['content'] = substr($content, $content_pos);
463
+ } else {
464
+ $current['content'] = '';
465
+ $length = 0;
466
+ while (substr($content, $content_pos, 2) != "\0\0") {
467
+ $temp = $this->_decode_ber($content, $length + $start, $content_pos);
468
+ $content_pos += $temp['length'];
469
+ // all subtags should be octet strings
470
+ //if ($temp['type'] != FILE_ASN1_TYPE_OCTET_STRING) {
471
+ // return false;
472
+ //}
473
+ $current['content'].= $temp['content'];
474
+ $length+= $temp['length'];
475
+ }
476
+ if (substr($content, $content_pos, 2) == "\0\0") {
477
+ $length+= 2; // +2 for the EOC
478
+ }
479
+ }
480
+ break;
481
+ case FILE_ASN1_TYPE_NULL:
482
+ // "The contents octets shall not contain any octets." -- paragraph 8.8.2
483
+ //if (strlen($content)) {
484
+ // return false;
485
+ //}
486
+ break;
487
+ case FILE_ASN1_TYPE_SEQUENCE:
488
+ case FILE_ASN1_TYPE_SET:
489
+ $offset = 0;
490
+ $current['content'] = array();
491
+ $content_len = strlen($content);
492
+ while ($content_pos < $content_len) {
493
+ // if indefinite length construction was used and we have an end-of-content string next
494
+ // see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
495
+ if (!isset($current['headerlength']) && substr($content, $content_pos, 2) == "\0\0") {
496
+ $length = $offset + 2; // +2 for the EOC
497
+ break 2;
498
+ }
499
+ $temp = $this->_decode_ber($content, $start + $offset, $content_pos);
500
+ $content_pos += $temp['length'];
501
+ $current['content'][] = $temp;
502
+ $offset+= $temp['length'];
503
+ }
504
+ break;
505
+ case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
506
+ $temp = ord($content[$content_pos++]);
507
+ $current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40);
508
+ $valuen = 0;
509
+ // process septets
510
+ $content_len = strlen($content);
511
+ while ($content_pos < $content_len) {
512
+ $temp = ord($content[$content_pos++]);
513
+ $valuen <<= 7;
514
+ $valuen |= $temp & 0x7F;
515
+ if (~$temp & 0x80) {
516
+ $current['content'].= ".$valuen";
517
+ $valuen = 0;
518
+ }
519
+ }
520
+ // the eighth bit of the last byte should not be 1
521
+ //if ($temp >> 7) {
522
+ // return false;
523
+ //}
524
+ break;
525
+ /* Each character string type shall be encoded as if it had been declared:
526
+ [UNIVERSAL x] IMPLICIT OCTET STRING
527
+
528
+ -- X.690-0207.pdf#page=23 (paragraph 8.21.3)
529
+
530
+ Per that, we're not going to do any validation. If there are any illegal characters in the string,
531
+ we don't really care */
532
+ case FILE_ASN1_TYPE_NUMERIC_STRING:
533
+ // 0,1,2,3,4,5,6,7,8,9, and space
534
+ case FILE_ASN1_TYPE_PRINTABLE_STRING:
535
+ // Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
536
+ // hyphen, full stop, solidus, colon, equal sign, question mark
537
+ case FILE_ASN1_TYPE_TELETEX_STRING:
538
+ // The Teletex character set in CCITT's T61, space, and delete
539
+ // see http://en.wikipedia.org/wiki/Teletex#Character_sets
540
+ case FILE_ASN1_TYPE_VIDEOTEX_STRING:
541
+ // The Videotex character set in CCITT's T.100 and T.101, space, and delete
542
+ case FILE_ASN1_TYPE_VISIBLE_STRING:
543
+ // Printing character sets of international ASCII, and space
544
+ case FILE_ASN1_TYPE_IA5_STRING:
545
+ // International Alphabet 5 (International ASCII)
546
+ case FILE_ASN1_TYPE_GRAPHIC_STRING:
547
+ // All registered G sets, and space
548
+ case FILE_ASN1_TYPE_GENERAL_STRING:
549
+ // All registered C and G sets, space and delete
550
+ case FILE_ASN1_TYPE_UTF8_STRING:
551
+ // ????
552
+ case FILE_ASN1_TYPE_BMP_STRING:
553
+ $current['content'] = substr($content, $content_pos);
554
+ break;
555
+ case FILE_ASN1_TYPE_UTC_TIME:
556
+ case FILE_ASN1_TYPE_GENERALIZED_TIME:
557
+ $current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
558
+ default:
559
+ }
560
+
561
+ $start+= $length;
562
+
563
+ // ie. length is the length of the full TLV encoding - it's not just the length of the value
564
+ return $current + array('length' => $start - $current['start']);
565
+ }
566
+
567
+ /**
568
+ * ASN.1 Map
569
+ *
570
+ * Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
571
+ *
572
+ * "Special" mappings may be applied on a per tag-name basis via $special.
573
+ *
574
+ * @param array $decoded
575
+ * @param array $mapping
576
+ * @param array $special
577
+ * @return array
578
+ * @access public
579
+ */
580
+ function asn1map($decoded, $mapping, $special = array())
581
+ {
582
+ if (isset($mapping['explicit']) && is_array($decoded['content'])) {
583
+ $decoded = $decoded['content'][0];
584
+ }
585
+
586
+ switch (true) {
587
+ case $mapping['type'] == FILE_ASN1_TYPE_ANY:
588
+ $intype = $decoded['type'];
589
+ if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || (ord($this->encoded[$decoded['start']]) & 0x20)) {
590
+ return new File_ASN1_Element(substr($this->encoded, $decoded['start'], $decoded['length']));
591
+ }
592
+ $inmap = $this->ANYmap[$intype];
593
+ if (is_string($inmap)) {
594
+ return array($inmap => $this->asn1map($decoded, array('type' => $intype) + $mapping, $special));
595
+ }
596
+ break;
597
+ case $mapping['type'] == FILE_ASN1_TYPE_CHOICE:
598
+ foreach ($mapping['children'] as $key => $option) {
599
+ switch (true) {
600
+ case isset($option['constant']) && $option['constant'] == $decoded['constant']:
601
+ case !isset($option['constant']) && $option['type'] == $decoded['type']:
602
+ $value = $this->asn1map($decoded, $option, $special);
603
+ break;
604
+ case !isset($option['constant']) && $option['type'] == FILE_ASN1_TYPE_CHOICE:
605
+ $v = $this->asn1map($decoded, $option, $special);
606
+ if (isset($v)) {
607
+ $value = $v;
608
+ }
609
+ }
610
+ if (isset($value)) {
611
+ if (isset($special[$key])) {
612
+ $value = call_user_func($special[$key], $value);
613
+ }
614
+ return array($key => $value);
615
+ }
616
+ }
617
+ return null;
618
+ case isset($mapping['implicit']):
619
+ case isset($mapping['explicit']):
620
+ case $decoded['type'] == $mapping['type']:
621
+ break;
622
+ default:
623
+ // if $decoded['type'] and $mapping['type'] are both strings, but different types of strings,
624
+ // let it through
625
+ switch (true) {
626
+ case $decoded['type'] < 18: // FILE_ASN1_TYPE_NUMERIC_STRING == 18
627
+ case $decoded['type'] > 30: // FILE_ASN1_TYPE_BMP_STRING == 30
628
+ case $mapping['type'] < 18:
629
+ case $mapping['type'] > 30:
630
+ return null;
631
+ }
632
+ }
633
+
634
+ if (isset($mapping['implicit'])) {
635
+ $decoded['type'] = $mapping['type'];
636
+ }
637
+
638
+ switch ($decoded['type']) {
639
+ case FILE_ASN1_TYPE_SEQUENCE:
640
+ $map = array();
641
+
642
+ // ignore the min and max
643
+ if (isset($mapping['min']) && isset($mapping['max'])) {
644
+ $child = $mapping['children'];
645
+ foreach ($decoded['content'] as $content) {
646
+ if (($map[] = $this->asn1map($content, $child, $special)) === null) {
647
+ return null;
648
+ }
649
+ }
650
+
651
+ return $map;
652
+ }
653
+
654
+ $n = count($decoded['content']);
655
+ $i = 0;
656
+
657
+ foreach ($mapping['children'] as $key => $child) {
658
+ $maymatch = $i < $n; // Match only existing input.
659
+ if ($maymatch) {
660
+ $temp = $decoded['content'][$i];
661
+
662
+ if ($child['type'] != FILE_ASN1_TYPE_CHOICE) {
663
+ // Get the mapping and input class & constant.
664
+ $childClass = $tempClass = FILE_ASN1_CLASS_UNIVERSAL;
665
+ $constant = null;
666
+ if (isset($temp['constant'])) {
667
+ $tempClass = isset($temp['class']) ? $temp['class'] : FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
668
+ }
669
+ if (isset($child['class'])) {
670
+ $childClass = $child['class'];
671
+ $constant = $child['cast'];
672
+ } elseif (isset($child['constant'])) {
673
+ $childClass = FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
674
+ $constant = $child['constant'];
675
+ }
676
+
677
+ if (isset($constant) && isset($temp['constant'])) {
678
+ // Can only match if constants and class match.
679
+ $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
680
+ } else {
681
+ // Can only match if no constant expected and type matches or is generic.
682
+ $maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], FILE_ASN1_TYPE_ANY, FILE_ASN1_TYPE_CHOICE)) !== false;
683
+ }
684
+ }
685
+ }
686
+
687
+ if ($maymatch) {
688
+ // Attempt submapping.
689
+ $candidate = $this->asn1map($temp, $child, $special);
690
+ $maymatch = $candidate !== null;
691
+ }
692
+
693
+ if ($maymatch) {
694
+ // Got the match: use it.
695
+ if (isset($special[$key])) {
696
+ $candidate = call_user_func($special[$key], $candidate);
697
+ }
698
+ $map[$key] = $candidate;
699
+ $i++;
700
+ } elseif (isset($child['default'])) {
701
+ $map[$key] = $child['default']; // Use default.
702
+ } elseif (!isset($child['optional'])) {
703
+ return null; // Syntax error.
704
+ }
705
+ }
706
+
707
+ // Fail mapping if all input items have not been consumed.
708
+ return $i < $n ? null: $map;
709
+
710
+ // the main diff between sets and sequences is the encapsulation of the foreach in another for loop
711
+ case FILE_ASN1_TYPE_SET:
712
+ $map = array();
713
+
714
+ // ignore the min and max
715
+ if (isset($mapping['min']) && isset($mapping['max'])) {
716
+ $child = $mapping['children'];
717
+ foreach ($decoded['content'] as $content) {
718
+ if (($map[] = $this->asn1map($content, $child, $special)) === null) {
719
+ return null;
720
+ }
721
+ }
722
+
723
+ return $map;
724
+ }
725
+
726
+ for ($i = 0; $i < count($decoded['content']); $i++) {
727
+ $temp = $decoded['content'][$i];
728
+ $tempClass = FILE_ASN1_CLASS_UNIVERSAL;
729
+ if (isset($temp['constant'])) {
730
+ $tempClass = isset($temp['class']) ? $temp['class'] : FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
731
+ }
732
+
733
+ foreach ($mapping['children'] as $key => $child) {
734
+ if (isset($map[$key])) {
735
+ continue;
736
+ }
737
+ $maymatch = true;
738
+ if ($child['type'] != FILE_ASN1_TYPE_CHOICE) {
739
+ $childClass = FILE_ASN1_CLASS_UNIVERSAL;
740
+ $constant = null;
741
+ if (isset($child['class'])) {
742
+ $childClass = $child['class'];
743
+ $constant = $child['cast'];
744
+ } elseif (isset($child['constant'])) {
745
+ $childClass = FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
746
+ $constant = $child['constant'];
747
+ }
748
+
749
+ if (isset($constant) && isset($temp['constant'])) {
750
+ // Can only match if constants and class match.
751
+ $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
752
+ } else {
753
+ // Can only match if no constant expected and type matches or is generic.
754
+ $maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], FILE_ASN1_TYPE_ANY, FILE_ASN1_TYPE_CHOICE)) !== false;
755
+ }
756
+ }
757
+
758
+ if ($maymatch) {
759
+ // Attempt submapping.
760
+ $candidate = $this->asn1map($temp, $child, $special);
761
+ $maymatch = $candidate !== null;
762
+ }
763
+
764
+ if (!$maymatch) {
765
+ break;
766
+ }
767
+
768
+ // Got the match: use it.
769
+ if (isset($special[$key])) {
770
+ $candidate = call_user_func($special[$key], $candidate);
771
+ }
772
+ $map[$key] = $candidate;
773
+ break;
774
+ }
775
+ }
776
+
777
+ foreach ($mapping['children'] as $key => $child) {
778
+ if (!isset($map[$key])) {
779
+ if (isset($child['default'])) {
780
+ $map[$key] = $child['default'];
781
+ } elseif (!isset($child['optional'])) {
782
+ return null;
783
+ }
784
+ }
785
+ }
786
+ return $map;
787
+ case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
788
+ return isset($this->oids[$decoded['content']]) ? $this->oids[$decoded['content']] : $decoded['content'];
789
+ case FILE_ASN1_TYPE_UTC_TIME:
790
+ case FILE_ASN1_TYPE_GENERALIZED_TIME:
791
+ if (isset($mapping['implicit'])) {
792
+ $decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
793
+ }
794
+ return @date($this->format, $decoded['content']);
795
+ case FILE_ASN1_TYPE_BIT_STRING:
796
+ if (isset($mapping['mapping'])) {
797
+ $offset = ord($decoded['content'][0]);
798
+ $size = (strlen($decoded['content']) - 1) * 8 - $offset;
799
+ /*
800
+ From X.680-0207.pdf#page=46 (21.7):
801
+
802
+ "When a "NamedBitList" is used in defining a bitstring type ASN.1 encoding rules are free to add (or remove)
803
+ arbitrarily any trailing 0 bits to (or from) values that are being encoded or decoded. Application designers should
804
+ therefore ensure that different semantics are not associated with such values which differ only in the number of trailing
805
+ 0 bits."
806
+ */
807
+ $bits = count($mapping['mapping']) == $size ? array() : array_fill(0, count($mapping['mapping']) - $size, false);
808
+ for ($i = strlen($decoded['content']) - 1; $i > 0; $i--) {
809
+ $current = ord($decoded['content'][$i]);
810
+ for ($j = $offset; $j < 8; $j++) {
811
+ $bits[] = (bool) ($current & (1 << $j));
812
+ }
813
+ $offset = 0;
814
+ }
815
+ $values = array();
816
+ $map = array_reverse($mapping['mapping']);
817
+ foreach ($map as $i => $value) {
818
+ if ($bits[$i]) {
819
+ $values[] = $value;
820
+ }
821
+ }
822
+ return $values;
823
+ }
824
+ case FILE_ASN1_TYPE_OCTET_STRING:
825
+ return base64_encode($decoded['content']);
826
+ case FILE_ASN1_TYPE_NULL:
827
+ return '';
828
+ case FILE_ASN1_TYPE_BOOLEAN:
829
+ return $decoded['content'];
830
+ case FILE_ASN1_TYPE_NUMERIC_STRING:
831
+ case FILE_ASN1_TYPE_PRINTABLE_STRING:
832
+ case FILE_ASN1_TYPE_TELETEX_STRING:
833
+ case FILE_ASN1_TYPE_VIDEOTEX_STRING:
834
+ case FILE_ASN1_TYPE_IA5_STRING:
835
+ case FILE_ASN1_TYPE_GRAPHIC_STRING:
836
+ case FILE_ASN1_TYPE_VISIBLE_STRING:
837
+ case FILE_ASN1_TYPE_GENERAL_STRING:
838
+ case FILE_ASN1_TYPE_UNIVERSAL_STRING:
839
+ case FILE_ASN1_TYPE_UTF8_STRING:
840
+ case FILE_ASN1_TYPE_BMP_STRING:
841
+ return $decoded['content'];
842
+ case FILE_ASN1_TYPE_INTEGER:
843
+ case FILE_ASN1_TYPE_ENUMERATED:
844
+ $temp = $decoded['content'];
845
+ if (isset($mapping['implicit'])) {
846
+ $temp = new Math_BigInteger($decoded['content'], -256);
847
+ }
848
+ if (isset($mapping['mapping'])) {
849
+ $temp = (int) $temp->toString();
850
+ return isset($mapping['mapping'][$temp]) ?
851
+ $mapping['mapping'][$temp] :
852
+ false;
853
+ }
854
+ return $temp;
855
+ }
856
+ }
857
+
858
+ /**
859
+ * ASN.1 Encode
860
+ *
861
+ * DER-encodes an ASN.1 semantic mapping ($mapping). Some libraries would probably call this function
862
+ * an ASN.1 compiler.
863
+ *
864
+ * "Special" mappings can be applied via $special.
865
+ *
866
+ * @param string $source
867
+ * @param string $mapping
868
+ * @param int $idx
869
+ * @return string
870
+ * @access public
871
+ */
872
+ function encodeDER($source, $mapping, $special = array())
873
+ {
874
+ $this->location = array();
875
+ return $this->_encode_der($source, $mapping, null, $special);
876
+ }
877
+
878
+ /**
879
+ * ASN.1 Encode (Helper function)
880
+ *
881
+ * @param string $source
882
+ * @param string $mapping
883
+ * @param int $idx
884
+ * @return string
885
+ * @access private
886
+ */
887
+ function _encode_der($source, $mapping, $idx = null, $special = array())
888
+ {
889
+ if (is_object($source) && strtolower(get_class($source)) == 'file_asn1_element') {
890
+ return $source->element;
891
+ }
892
+
893
+ // do not encode (implicitly optional) fields with value set to default
894
+ if (isset($mapping['default']) && $source === $mapping['default']) {
895
+ return '';
896
+ }
897
+
898
+ if (isset($idx)) {
899
+ if (isset($special[$idx])) {
900
+ $source = call_user_func($special[$idx], $source);
901
+ }
902
+ $this->location[] = $idx;
903
+ }
904
+
905
+ $tag = $mapping['type'];
906
+
907
+ switch ($tag) {
908
+ case FILE_ASN1_TYPE_SET: // Children order is not important, thus process in sequence.
909
+ case FILE_ASN1_TYPE_SEQUENCE:
910
+ $tag|= 0x20; // set the constructed bit
911
+
912
+ // ignore the min and max
913
+ if (isset($mapping['min']) && isset($mapping['max'])) {
914
+ $value = array();
915
+ $child = $mapping['children'];
916
+
917
+ foreach ($source as $content) {
918
+ $temp = $this->_encode_der($content, $child, null, $special);
919
+ if ($temp === false) {
920
+ return false;
921
+ }
922
+ $value[]= $temp;
923
+ }
924
+ /* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared
925
+ as octet strings with the shorter components being padded at their trailing end with 0-octets.
926
+ NOTE - The padding octets are for comparison purposes only and do not appear in the encodings."
927
+
928
+ -- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */
929
+ if ($mapping['type'] == FILE_ASN1_TYPE_SET) {
930
+ sort($value);
931
+ }
932
+ $value = implode($value, '');
933
+ break;
934
+ }
935
+
936
+ $value = '';
937
+ foreach ($mapping['children'] as $key => $child) {
938
+ if (!array_key_exists($key, $source)) {
939
+ if (!isset($child['optional'])) {
940
+ return false;
941
+ }
942
+ continue;
943
+ }
944
+
945
+ $temp = $this->_encode_der($source[$key], $child, $key, $special);
946
+ if ($temp === false) {
947
+ return false;
948
+ }
949
+
950
+ // An empty child encoding means it has been optimized out.
951
+ // Else we should have at least one tag byte.
952
+ if ($temp === '') {
953
+ continue;
954
+ }
955
+
956
+ // if isset($child['constant']) is true then isset($child['optional']) should be true as well
957
+ if (isset($child['constant'])) {
958
+ /*
959
+ From X.680-0207.pdf#page=58 (30.6):
960
+
961
+ "The tagging construction specifies explicit tagging if any of the following holds:
962
+ ...
963
+ c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or
964
+ AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or
965
+ an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
966
+ */
967
+ if (isset($child['explicit']) || $child['type'] == FILE_ASN1_TYPE_CHOICE) {
968
+ $subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
969
+ $temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
970
+ } else {
971
+ $subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
972
+ $temp = $subtag . substr($temp, 1);
973
+ }
974
+ }
975
+ $value.= $temp;
976
+ }
977
+ break;
978
+ case FILE_ASN1_TYPE_CHOICE:
979
+ $temp = false;
980
+
981
+ foreach ($mapping['children'] as $key => $child) {
982
+ if (!isset($source[$key])) {
983
+ continue;
984
+ }
985
+
986
+ $temp = $this->_encode_der($source[$key], $child, $key, $special);
987
+ if ($temp === false) {
988
+ return false;
989
+ }
990
+
991
+ // An empty child encoding means it has been optimized out.
992
+ // Else we should have at least one tag byte.
993
+ if ($temp === '') {
994
+ continue;
995
+ }
996
+
997
+ $tag = ord($temp[0]);
998
+
999
+ // if isset($child['constant']) is true then isset($child['optional']) should be true as well
1000
+ if (isset($child['constant'])) {
1001
+ if (isset($child['explicit']) || $child['type'] == FILE_ASN1_TYPE_CHOICE) {
1002
+ $subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
1003
+ $temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
1004
+ } else {
1005
+ $subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
1006
+ $temp = $subtag . substr($temp, 1);
1007
+ }
1008
+ }
1009
+ }
1010
+
1011
+ if (isset($idx)) {
1012
+ array_pop($this->location);
1013
+ }
1014
+
1015
+ if ($temp && isset($mapping['cast'])) {
1016
+ $temp[0] = chr(($mapping['class'] << 6) | ($tag & 0x20) | $mapping['cast']);
1017
+ }
1018
+
1019
+ return $temp;
1020
+ case FILE_ASN1_TYPE_INTEGER:
1021
+ case FILE_ASN1_TYPE_ENUMERATED:
1022
+ if (!isset($mapping['mapping'])) {
1023
+ if (is_numeric($source)) {
1024
+ $source = new Math_BigInteger($source);
1025
+ }
1026
+ $value = $source->toBytes(true);
1027
+ } else {
1028
+ $value = array_search($source, $mapping['mapping']);
1029
+ if ($value === false) {
1030
+ return false;
1031
+ }
1032
+ $value = new Math_BigInteger($value);
1033
+ $value = $value->toBytes(true);
1034
+ }
1035
+ if (!strlen($value)) {
1036
+ $value = chr(0);
1037
+ }
1038
+ break;
1039
+ case FILE_ASN1_TYPE_UTC_TIME:
1040
+ case FILE_ASN1_TYPE_GENERALIZED_TIME:
1041
+ $format = $mapping['type'] == FILE_ASN1_TYPE_UTC_TIME ? 'y' : 'Y';
1042
+ $format.= 'mdHis';
1043
+ $value = @gmdate($format, strtotime($source)) . 'Z';
1044
+ break;
1045
+ case FILE_ASN1_TYPE_BIT_STRING:
1046
+ if (isset($mapping['mapping'])) {
1047
+ $bits = array_fill(0, count($mapping['mapping']), 0);
1048
+ $size = 0;
1049
+ for ($i = 0; $i < count($mapping['mapping']); $i++) {
1050
+ if (in_array($mapping['mapping'][$i], $source)) {
1051
+ $bits[$i] = 1;
1052
+ $size = $i;
1053
+ }
1054
+ }
1055
+
1056
+ if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) {
1057
+ $size = $mapping['min'] - 1;
1058
+ }
1059
+
1060
+ $offset = 8 - (($size + 1) & 7);
1061
+ $offset = $offset !== 8 ? $offset : 0;
1062
+
1063
+ $value = chr($offset);
1064
+
1065
+ for ($i = $size + 1; $i < count($mapping['mapping']); $i++) {
1066
+ unset($bits[$i]);
1067
+ }
1068
+
1069
+ $bits = implode('', array_pad($bits, $size + $offset + 1, 0));
1070
+ $bytes = explode(' ', rtrim(chunk_split($bits, 8, ' ')));
1071
+ foreach ($bytes as $byte) {
1072
+ $value.= chr(bindec($byte));
1073
+ }
1074
+
1075
+ break;
1076
+ }
1077
+ case FILE_ASN1_TYPE_OCTET_STRING:
1078
+ /* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
1079
+ the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
1080
+
1081
+ -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
1082
+ $value = base64_decode($source);
1083
+ break;
1084
+ case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
1085
+ $oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
1086
+ if ($oid === false) {
1087
+ user_error('Invalid OID');
1088
+ return false;
1089
+ }
1090
+ $value = '';
1091
+ $parts = explode('.', $oid);
1092
+ $value = chr(40 * $parts[0] + $parts[1]);
1093
+ for ($i = 2; $i < count($parts); $i++) {
1094
+ $temp = '';
1095
+ if (!$parts[$i]) {
1096
+ $temp = "\0";
1097
+ } else {
1098
+ while ($parts[$i]) {
1099
+ $temp = chr(0x80 | ($parts[$i] & 0x7F)) . $temp;
1100
+ $parts[$i] >>= 7;
1101
+ }
1102
+ $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
1103
+ }
1104
+ $value.= $temp;
1105
+ }
1106
+ break;
1107
+ case FILE_ASN1_TYPE_ANY:
1108
+ $loc = $this->location;
1109
+ if (isset($idx)) {
1110
+ array_pop($this->location);
1111
+ }
1112
+
1113
+ switch (true) {
1114
+ case !isset($source):
1115
+ return $this->_encode_der(null, array('type' => FILE_ASN1_TYPE_NULL) + $mapping, null, $special);
1116
+ case is_int($source):
1117
+ case is_object($source) && strtolower(get_class($source)) == 'math_biginteger':
1118
+ return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping, null, $special);
1119
+ case is_float($source):
1120
+ return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping, null, $special);
1121
+ case is_bool($source):
1122
+ return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping, null, $special);
1123
+ case is_array($source) && count($source) == 1:
1124
+ $typename = implode('', array_keys($source));
1125
+ $outtype = array_search($typename, $this->ANYmap, true);
1126
+ if ($outtype !== false) {
1127
+ return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special);
1128
+ }
1129
+ }
1130
+
1131
+ $filters = $this->filters;
1132
+ foreach ($loc as $part) {
1133
+ if (!isset($filters[$part])) {
1134
+ $filters = false;
1135
+ break;
1136
+ }
1137
+ $filters = $filters[$part];
1138
+ }
1139
+ if ($filters === false) {
1140
+ user_error('No filters defined for ' . implode('/', $loc));
1141
+ return false;
1142
+ }
1143
+ return $this->_encode_der($source, $filters + $mapping, null, $special);
1144
+ case FILE_ASN1_TYPE_NULL:
1145
+ $value = '';
1146
+ break;
1147
+ case FILE_ASN1_TYPE_NUMERIC_STRING:
1148
+ case FILE_ASN1_TYPE_TELETEX_STRING:
1149
+ case FILE_ASN1_TYPE_PRINTABLE_STRING:
1150
+ case FILE_ASN1_TYPE_UNIVERSAL_STRING:
1151
+ case FILE_ASN1_TYPE_UTF8_STRING:
1152
+ case FILE_ASN1_TYPE_BMP_STRING:
1153
+ case FILE_ASN1_TYPE_IA5_STRING:
1154
+ case FILE_ASN1_TYPE_VISIBLE_STRING:
1155
+ case FILE_ASN1_TYPE_VIDEOTEX_STRING:
1156
+ case FILE_ASN1_TYPE_GRAPHIC_STRING:
1157
+ case FILE_ASN1_TYPE_GENERAL_STRING:
1158
+ $value = $source;
1159
+ break;
1160
+ case FILE_ASN1_TYPE_BOOLEAN:
1161
+ $value = $source ? "\xFF" : "\x00";
1162
+ break;
1163
+ default:
1164
+ user_error('Mapping provides no type definition for ' . implode('/', $this->location));
1165
+ return false;
1166
+ }
1167
+
1168
+ if (isset($idx)) {
1169
+ array_pop($this->location);
1170
+ }
1171
+
1172
+ if (isset($mapping['cast'])) {
1173
+ if (isset($mapping['explicit']) || $mapping['type'] == FILE_ASN1_TYPE_CHOICE) {
1174
+ $value = chr($tag) . $this->_encodeLength(strlen($value)) . $value;
1175
+ $tag = ($mapping['class'] << 6) | 0x20 | $mapping['cast'];
1176
+ } else {
1177
+ $tag = ($mapping['class'] << 6) | (ord($temp[0]) & 0x20) | $mapping['cast'];
1178
+ }
1179
+ }
1180
+
1181
+ return chr($tag) . $this->_encodeLength(strlen($value)) . $value;
1182
+ }
1183
+
1184
+ /**
1185
+ * DER-encode the length
1186
+ *
1187
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
1188
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
1189
+ *
1190
+ * @access private
1191
+ * @param int $length
1192
+ * @return string
1193
+ */
1194
+ function _encodeLength($length)
1195
+ {
1196
+ if ($length <= 0x7F) {
1197
+ return chr($length);
1198
+ }
1199
+
1200
+ $temp = ltrim(pack('N', $length), chr(0));
1201
+ return pack('Ca*', 0x80 | strlen($temp), $temp);
1202
+ }
1203
+
1204
+ /**
1205
+ * BER-decode the time
1206
+ *
1207
+ * Called by _decode_ber() and in the case of implicit tags asn1map().
1208
+ *
1209
+ * @access private
1210
+ * @param string $content
1211
+ * @param int $tag
1212
+ * @return string
1213
+ */
1214
+ function _decodeTime($content, $tag)
1215
+ {
1216
+ /* UTCTime:
1217
+ http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
1218
+ http://www.obj-sys.com/asn1tutorial/node15.html
1219
+
1220
+ GeneralizedTime:
1221
+ http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
1222
+ http://www.obj-sys.com/asn1tutorial/node14.html */
1223
+
1224
+ $pattern = $tag == FILE_ASN1_TYPE_UTC_TIME ?
1225
+ '#^(..)(..)(..)(..)(..)(..)?(.*)$#' :
1226
+ '#(....)(..)(..)(..)(..)(..).*([Z+-].*)$#';
1227
+
1228
+ preg_match($pattern, $content, $matches);
1229
+
1230
+ list(, $year, $month, $day, $hour, $minute, $second, $timezone) = $matches;
1231
+
1232
+ if ($tag == FILE_ASN1_TYPE_UTC_TIME) {
1233
+ $year = $year >= 50 ? "19$year" : "20$year";
1234
+ }
1235
+
1236
+ if ($timezone == 'Z') {
1237
+ $mktime = 'gmmktime';
1238
+ $timezone = 0;
1239
+ } elseif (preg_match('#([+-])(\d\d)(\d\d)#', $timezone, $matches)) {
1240
+ $mktime = 'gmmktime';
1241
+ $timezone = 60 * $matches[3] + 3600 * $matches[2];
1242
+ if ($matches[1] == '-') {
1243
+ $timezone = -$timezone;
1244
+ }
1245
+ } else {
1246
+ $mktime = 'mktime';
1247
+ $timezone = 0;
1248
+ }
1249
+
1250
+ return @$mktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year) + $timezone;
1251
+ }
1252
+
1253
+ /**
1254
+ * Set the time format
1255
+ *
1256
+ * Sets the time / date format for asn1map().
1257
+ *
1258
+ * @access public
1259
+ * @param string $format
1260
+ */
1261
+ function setTimeFormat($format)
1262
+ {
1263
+ $this->format = $format;
1264
+ }
1265
+
1266
+ /**
1267
+ * Load OIDs
1268
+ *
1269
+ * Load the relevant OIDs for a particular ASN.1 semantic mapping.
1270
+ *
1271
+ * @access public
1272
+ * @param array $oids
1273
+ */
1274
+ function loadOIDs($oids)
1275
+ {
1276
+ $this->oids = $oids;
1277
+ }
1278
+
1279
+ /**
1280
+ * Load filters
1281
+ *
1282
+ * See File_X509, etc, for an example.
1283
+ *
1284
+ * @access public
1285
+ * @param array $filters
1286
+ */
1287
+ function loadFilters($filters)
1288
+ {
1289
+ $this->filters = $filters;
1290
+ }
1291
+
1292
+ /**
1293
+ * String Shift
1294
+ *
1295
+ * Inspired by array_shift
1296
+ *
1297
+ * @param string $string
1298
+ * @param int $index
1299
+ * @return string
1300
+ * @access private
1301
+ */
1302
+ function _string_shift(&$string, $index = 1)
1303
+ {
1304
+ $substr = substr($string, 0, $index);
1305
+ $string = substr($string, $index);
1306
+ return $substr;
1307
+ }
1308
+
1309
+ /**
1310
+ * String type conversion
1311
+ *
1312
+ * This is a lazy conversion, dealing only with character size.
1313
+ * No real conversion table is used.
1314
+ *
1315
+ * @param string $in
1316
+ * @param int $from
1317
+ * @param int $to
1318
+ * @return string
1319
+ * @access public
1320
+ */
1321
+ function convert($in, $from = FILE_ASN1_TYPE_UTF8_STRING, $to = FILE_ASN1_TYPE_UTF8_STRING)
1322
+ {
1323
+ if (!isset($this->stringTypeSize[$from]) || !isset($this->stringTypeSize[$to])) {
1324
+ return false;
1325
+ }
1326
+ $insize = $this->stringTypeSize[$from];
1327
+ $outsize = $this->stringTypeSize[$to];
1328
+ $inlength = strlen($in);
1329
+ $out = '';
1330
+
1331
+ for ($i = 0; $i < $inlength;) {
1332
+ if ($inlength - $i < $insize) {
1333
+ return false;
1334
+ }
1335
+
1336
+ // Get an input character as a 32-bit value.
1337
+ $c = ord($in[$i++]);
1338
+ switch (true) {
1339
+ case $insize == 4:
1340
+ $c = ($c << 8) | ord($in[$i++]);
1341
+ $c = ($c << 8) | ord($in[$i++]);
1342
+ case $insize == 2:
1343
+ $c = ($c << 8) | ord($in[$i++]);
1344
+ case $insize == 1:
1345
+ break;
1346
+ case ($c & 0x80) == 0x00:
1347
+ break;
1348
+ case ($c & 0x40) == 0x00:
1349
+ return false;
1350
+ default:
1351
+ $bit = 6;
1352
+ do {
1353
+ if ($bit > 25 || $i >= $inlength || (ord($in[$i]) & 0xC0) != 0x80) {
1354
+ return false;
1355
+ }
1356
+ $c = ($c << 6) | (ord($in[$i++]) & 0x3F);
1357
+ $bit += 5;
1358
+ $mask = 1 << $bit;
1359
+ } while ($c & $bit);
1360
+ $c &= $mask - 1;
1361
+ break;
1362
+ }
1363
+
1364
+ // Convert and append the character to output string.
1365
+ $v = '';
1366
+ switch (true) {
1367
+ case $outsize == 4:
1368
+ $v .= chr($c & 0xFF);
1369
+ $c >>= 8;
1370
+ $v .= chr($c & 0xFF);
1371
+ $c >>= 8;
1372
+ case $outsize == 2:
1373
+ $v .= chr($c & 0xFF);
1374
+ $c >>= 8;
1375
+ case $outsize == 1:
1376
+ $v .= chr($c & 0xFF);
1377
+ $c >>= 8;
1378
+ if ($c) {
1379
+ return false;
1380
+ }
1381
+ break;
1382
+ case ($c & 0x80000000) != 0:
1383
+ return false;
1384
+ case $c >= 0x04000000:
1385
+ $v .= chr(0x80 | ($c & 0x3F));
1386
+ $c = ($c >> 6) | 0x04000000;
1387
+ case $c >= 0x00200000:
1388
+ $v .= chr(0x80 | ($c & 0x3F));
1389
+ $c = ($c >> 6) | 0x00200000;
1390
+ case $c >= 0x00010000:
1391
+ $v .= chr(0x80 | ($c & 0x3F));
1392
+ $c = ($c >> 6) | 0x00010000;
1393
+ case $c >= 0x00000800:
1394
+ $v .= chr(0x80 | ($c & 0x3F));
1395
+ $c = ($c >> 6) | 0x00000800;
1396
+ case $c >= 0x00000080:
1397
+ $v .= chr(0x80 | ($c & 0x3F));
1398
+ $c = ($c >> 6) | 0x000000C0;
1399
+ default:
1400
+ $v .= chr($c);
1401
+ break;
1402
+ }
1403
+ $out .= strrev($v);
1404
+ }
1405
+ return $out;
1406
+ }
1407
+ }
lib/sc/connector/vendor/phpseclib/phpseclib/phpseclib/File/X509.php ADDED
@@ -0,0 +1,4887 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP X.509 Parser
5
+ *
6
+ * PHP versions 4 and 5
7
+ *
8
+ * Encode and decode X.509 certificates.
9
+ *
10
+ * The extensions are from {@link http://tools.ietf.org/html/rfc5280 RFC5280} and
11
+ * {@link http://web.archive.org/web/19961027104704/http://www3.netscape.com/eng/security/cert-exts.html Netscape Certificate Extensions}.
12
+ *
13
+ * Note that loading an X.509 certificate and resaving it may invalidate the signature. The reason being that the signature is based on a
14
+ * portion of the certificate that contains optional parameters with default values. ie. if the parameter isn't there the default value is
15
+ * used. Problem is, if the parameter is there and it just so happens to have the default value there are two ways that that parameter can
16
+ * be encoded. It can be encoded explicitly or left out all together. This would effect the signature value and thus may invalidate the
17
+ * the certificate all together unless the certificate is re-signed.
18
+ *
19
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ * of this software and associated documentation files (the "Software"), to deal
21
+ * in the Software without restriction, including without limitation the rights
22
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ * copies of the Software, and to permit persons to whom the Software is
24
+ * furnished to do so, subject to the following conditions:
25
+ *
26
+ * The above copyright notice and this permission notice shall be included in
27
+ * all copies or substantial portions of the Software.
28
+ *
29
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35
+ * THE SOFTWARE.
36
+ *
37
+ * @category File
38
+ * @package File_X509
39
+ * @author Jim Wigginton <terrafrost@php.net>
40
+ * @copyright 2012 Jim Wigginton
41
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
42
+ * @link http://phpseclib.sourceforge.net
43
+ */
44
+
45
+ /**
46
+ * Include File_ASN1
47
+ */
48
+ if (!class_exists('File_ASN1')) {
49
+ include_once 'ASN1.php';
50
+ }
51
+
52
+ /**
53
+ * Flag to only accept signatures signed by certificate authorities
54
+ *
55
+ * Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
56
+ *
57
+ * @access public
58
+ */
59
+ define('FILE_X509_VALIDATE_SIGNATURE_BY_CA', 1);
60
+
61
+ /**#@+
62
+ * @access public
63
+ * @see self::getDN()
64
+ */
65
+ /**
66
+ * Return internal array representation
67
+ */
68
+ define('FILE_X509_DN_ARRAY', 0);
69
+ /**
70
+ * Return string
71
+ */
72
+ define('FILE_X509_DN_STRING', 1);
73
+ /**
74
+ * Return ASN.1 name string
75
+ */
76
+ define('FILE_X509_DN_ASN1', 2);
77
+ /**
78
+ * Return OpenSSL compatible array
79
+ */
80
+ define('FILE_X509_DN_OPENSSL', 3);
81
+ /**
82
+ * Return canonical ASN.1 RDNs string
83
+ */
84
+ define('FILE_X509_DN_CANON', 4);
85
+ /**
86
+ * Return name hash for file indexing
87
+ */
88
+ define('FILE_X509_DN_HASH', 5);
89
+ /**#@-*/
90
+
91
+ /**#@+
92
+ * @access public
93
+ * @see self::saveX509()
94
+ * @see self::saveCSR()
95
+ * @see self::saveCRL()
96
+ */
97
+ /**
98
+ * Save as PEM
99
+ *
100
+ * ie. a base64-encoded PEM with a header and a footer
101
+ */
102
+ define('FILE_X509_FORMAT_PEM', 0);
103
+ /**
104
+ * Save as DER
105
+ */
106
+ define('FILE_X509_FORMAT_DER', 1);
107
+ /**
108
+ * Save as a SPKAC
109
+ *
110
+ * Only works on CSRs. Not currently supported.
111
+ */
112
+ define('FILE_X509_FORMAT_SPKAC', 2);
113
+ /**
114
+ * Auto-detect the format
115
+ *
116
+ * Used only by the load*() functions
117
+ */
118
+ define('FILE_X509_FORMAT_AUTO_DETECT', 3);
119
+ /**#@-*/
120
+
121
+ /**
122
+ * Attribute value disposition.
123
+ * If disposition is >= 0, this is the index of the target value.
124
+ */
125
+ define('FILE_X509_ATTR_ALL', -1); // All attribute values (array).
126
+ define('FILE_X509_ATTR_APPEND', -2); // Add a value.
127
+ define('FILE_X509_ATTR_REPLACE', -3); // Clear first, then add a value.
128
+
129
+ /**
130
+ * Pure-PHP X.509 Parser
131
+ *
132
+ * @package File_X509
133
+ * @author Jim Wigginton <terrafrost@php.net>
134
+ * @access public
135
+ */
136
+ class File_X509
137
+ {
138
+ /**
139
+ * ASN.1 syntax for X.509 certificates
140
+ *
141
+ * @var array
142
+ * @access private
143
+ */
144
+ var $Certificate;
145
+
146
+ /**#@+
147
+ * ASN.1 syntax for various extensions
148
+ *
149
+ * @access private
150
+ */
151
+ var $DirectoryString;
152
+ var $PKCS9String;
153
+ var $AttributeValue;
154
+ var $Extensions;
155
+ var $KeyUsage;
156
+ var $ExtKeyUsageSyntax;
157
+ var $BasicConstraints;
158
+ var $KeyIdentifier;
159
+ var $CRLDistributionPoints;
160
+ var $AuthorityKeyIdentifier;
161
+ var $CertificatePolicies;
162
+ var $AuthorityInfoAccessSyntax;
163
+ var $SubjectAltName;
164
+ var $SubjectDirectoryAttributes;
165
+ var $PrivateKeyUsagePeriod;
166
+ var $IssuerAltName;
167
+ var $PolicyMappings;
168
+ var $NameConstraints;
169
+
170
+ var $CPSuri;
171
+ var $UserNotice;
172
+
173
+ var $netscape_cert_type;
174
+ var $netscape_comment;
175
+ var $netscape_ca_policy_url;
176
+
177
+ var $Name;
178
+ var $RelativeDistinguishedName;
179
+ var $CRLNumber;
180
+ var $CRLReason;
181
+ var $IssuingDistributionPoint;
182
+ var $InvalidityDate;
183
+ var $CertificateIssuer;
184
+ var $HoldInstructionCode;
185
+ var $SignedPublicKeyAndChallenge;
186
+ /**#@-*/
187
+
188
+ /**#@+
189
+ * ASN.1 syntax for various DN attributes
190
+ *
191
+ * @access private
192
+ */
193
+ var $PostalAddress;
194
+ /**#@-*/
195
+
196
+ /**
197
+ * ASN.1 syntax for Certificate Signing Requests (RFC2986)
198
+ *
199
+ * @var array
200
+ * @access private
201
+ */
202
+ var $CertificationRequest;
203
+
204
+ /**
205
+ * ASN.1 syntax for Certificate Revocation Lists (RFC5280)
206
+ *
207
+ * @var array
208
+ * @access private
209
+ */
210
+ var $CertificateList;
211
+
212
+ /**
213
+ * Distinguished Name
214
+ *
215
+ * @var array
216
+ * @access private
217
+ */
218
+ var $dn;
219
+
220
+ /**
221
+ * Public key
222
+ *
223
+ * @var string
224
+ * @access private
225
+ */
226
+ var $publicKey;
227
+
228
+ /**
229
+ * Private key
230
+ *
231
+ * @var string
232
+ * @access private
233
+ */
234
+ var $privateKey;
235
+
236
+ /**
237
+ * Object identifiers for X.509 certificates
238
+ *
239
+ * @var array
240
+ * @access private
241
+ * @link http://en.wikipedia.org/wiki/Object_identifier
242
+ */
243
+ var $oids;
244
+
245
+ /**
246
+ * The certificate authorities
247
+ *
248
+ * @var array
249
+ * @access private
250
+ */
251
+ var $CAs;
252
+
253
+ /**
254
+ * The currently loaded certificate
255
+ *
256
+ * @var array
257
+ * @access private
258
+ */
259
+ var $currentCert;
260
+
261
+ /**
262
+ * The signature subject
263
+ *
264
+ * There's no guarantee File_X509 is going to re-encode an X.509 cert in the same way it was originally
265
+ * encoded so we take save the portion of the original cert that the signature would have made for.
266
+ *
267
+ * @var string
268
+ * @access private
269
+ */
270
+ var $signatureSubject;
271
+
272
+ /**
273
+ * Certificate Start Date
274
+ *
275
+ * @var string
276
+ * @access private
277
+ */
278
+ var $startDate;
279
+
280
+ /**
281
+ * Certificate End Date
282
+ *
283
+ * @var string
284
+ * @access private
285
+ */
286
+ var $endDate;
287
+
288
+ /**
289
+ * Serial Number
290
+ *
291
+ * @var string
292
+ * @access private
293
+ */
294
+ var $serialNumber;
295
+
296
+ /**
297
+ * Key Identifier
298
+ *
299
+ * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and
300
+ * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}.
301
+ *
302
+ * @var string
303
+ * @access private
304
+ */
305
+ var $currentKeyIdentifier;
306
+
307
+ /**
308
+ * CA Flag
309
+ *
310
+ * @var bool
311
+ * @access private
312
+ */
313
+ var $caFlag = false;
314
+
315
+ /**
316
+ * SPKAC Challenge
317
+ *
318
+ * @var string
319
+ * @access private
320
+ */
321
+ var $challenge;
322
+
323
+ /**
324
+ * Default Constructor.
325
+ *
326
+ * @return File_X509
327
+ * @access public
328
+ */
329
+ function __construct()
330
+ {
331
+ if (!class_exists('Math_BigInteger')) {
332
+ include_once 'Math/BigInteger.php';
333
+ }
334
+
335
+ // Explicitly Tagged Module, 1988 Syntax
336
+ // http://tools.ietf.org/html/rfc5280#appendix-A.1
337
+
338
+ $this->DirectoryString = array(
339
+ 'type' => FILE_ASN1_TYPE_CHOICE,
340
+ 'children' => array(
341
+ 'teletexString' => array('type' => FILE_ASN1_TYPE_TELETEX_STRING),
342
+ 'printableString' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING),
343
+ 'universalString' => array('type' => FILE_ASN1_TYPE_UNIVERSAL_STRING),
344
+ 'utf8String' => array('type' => FILE_ASN1_TYPE_UTF8_STRING),
345
+ 'bmpString' => array('type' => FILE_ASN1_TYPE_BMP_STRING)
346
+ )
347
+ );
348
+
349
+ $this->PKCS9String = array(
350
+ 'type' => FILE_ASN1_TYPE_CHOICE,
351
+ 'children' => array(
352
+ 'ia5String' => array('type' => FILE_ASN1_TYPE_IA5_STRING),
353
+ 'directoryString' => $this->DirectoryString
354
+ )
355
+ );
356
+
357
+ $this->AttributeValue = array('type' => FILE_ASN1_TYPE_ANY);
358
+
359
+ $AttributeType = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
360
+
361
+ $AttributeTypeAndValue = array(
362
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
363
+ 'children' => array(
364
+ 'type' => $AttributeType,
365
+ 'value'=> $this->AttributeValue
366
+ )
367
+ );
368
+
369
+ /*
370
+ In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare,
371
+ but they can be useful at times when either there is no unique attribute in the entry or you
372
+ want to ensure that the entry's DN contains some useful identifying information.
373
+
374
+ - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
375
+ */
376
+ $this->RelativeDistinguishedName = array(
377
+ 'type' => FILE_ASN1_TYPE_SET,
378
+ 'min' => 1,
379
+ 'max' => -1,
380
+ 'children' => $AttributeTypeAndValue
381
+ );
382
+
383
+ // http://tools.ietf.org/html/rfc5280#section-4.1.2.4
384
+ $RDNSequence = array(
385
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
386
+ // RDNSequence does not define a min or a max, which means it doesn't have one
387
+ 'min' => 0,
388
+ 'max' => -1,
389
+ 'children' => $this->RelativeDistinguishedName
390
+ );
391
+
392
+ $this->Name = array(
393
+ 'type' => FILE_ASN1_TYPE_CHOICE,
394
+ 'children' => array(
395
+ 'rdnSequence' => $RDNSequence
396
+ )
397
+ );
398
+
399
+ // http://tools.ietf.org/html/rfc5280#section-4.1.1.2
400
+ $AlgorithmIdentifier = array(
401
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
402
+ 'children' => array(
403
+ 'algorithm' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
404
+ 'parameters' => array(
405
+ 'type' => FILE_ASN1_TYPE_ANY,
406
+ 'optional' => true
407
+ )
408
+ )
409
+ );
410
+
411
+ /*
412
+ A certificate using system MUST reject the certificate if it encounters
413
+ a critical extension it does not recognize; however, a non-critical
414
+ extension may be ignored if it is not recognized.
415
+
416
+ http://tools.ietf.org/html/rfc5280#section-4.2
417
+ */
418
+ $Extension = array(
419
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
420
+ 'children' => array(
421
+ 'extnId' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
422
+ 'critical' => array(
423
+ 'type' => FILE_ASN1_TYPE_BOOLEAN,
424
+ 'optional' => true,
425
+ 'default' => false
426
+ ),
427
+ 'extnValue' => array('type' => FILE_ASN1_TYPE_OCTET_STRING)
428
+ )
429
+ );
430
+
431
+ $this->Extensions = array(
432
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
433
+ 'min' => 1,
434
+ // technically, it's MAX, but we'll assume anything < 0 is MAX
435
+ 'max' => -1,
436
+ // if 'children' isn't an array then 'min' and 'max' must be defined
437
+ 'children' => $Extension
438
+ );
439
+
440
+ $SubjectPublicKeyInfo = array(
441
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
442
+ 'children' => array(
443
+ 'algorithm' => $AlgorithmIdentifier,
444
+ 'subjectPublicKey' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
445
+ )
446
+ );
447
+
448
+ $UniqueIdentifier = array('type' => FILE_ASN1_TYPE_BIT_STRING);
449
+
450
+ $Time = array(
451
+ 'type' => FILE_ASN1_TYPE_CHOICE,
452
+ 'children' => array(
453
+ 'utcTime' => array('type' => FILE_ASN1_TYPE_UTC_TIME),
454
+ 'generalTime' => array('type' => FILE_ASN1_TYPE_GENERALIZED_TIME)
455
+ )
456
+ );
457
+
458
+ // http://tools.ietf.org/html/rfc5280#section-4.1.2.5
459
+ $Validity = array(
460
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
461
+ 'children' => array(
462
+ 'notBefore' => $Time,
463
+ 'notAfter' => $Time
464
+ )
465
+ );
466
+
467
+ $CertificateSerialNumber = array('type' => FILE_ASN1_TYPE_INTEGER);
468
+
469
+ $Version = array(
470
+ 'type' => FILE_ASN1_TYPE_INTEGER,
471
+ 'mapping' => array('v1', 'v2', 'v3')
472
+ );
473
+
474
+ // assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm'])
475
+ $TBSCertificate = array(
476
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
477
+ 'children' => array(
478
+ // technically, default implies optional, but we'll define it as being optional, none-the-less, just to
479
+ // reenforce that fact
480
+ 'version' => array(
481
+ 'constant' => 0,
482
+ 'optional' => true,
483
+ 'explicit' => true,
484
+ 'default' => 'v1'
485
+ ) + $Version,
486
+ 'serialNumber' => $CertificateSerialNumber,
487
+ 'signature' => $AlgorithmIdentifier,
488
+ 'issuer' => $this->Name,
489
+ 'validity' => $Validity,
490
+ 'subject' => $this->Name,
491
+ 'subjectPublicKeyInfo' => $SubjectPublicKeyInfo,
492
+ // implicit means that the T in the TLV structure is to be rewritten, regardless of the type
493
+ 'issuerUniqueID' => array(
494
+ 'constant' => 1,
495
+ 'optional' => true,
496
+ 'implicit' => true
497
+ ) + $UniqueIdentifier,
498
+ 'subjectUniqueID' => array(
499
+ 'constant' => 2,
500
+ 'optional' => true,
501
+ 'implicit' => true
502
+ ) + $UniqueIdentifier,
503
+ // <http://tools.ietf.org/html/rfc2459#page-74> doesn't use the EXPLICIT keyword but if
504
+ // it's not IMPLICIT, it's EXPLICIT
505
+ 'extensions' => array(
506
+ 'constant' => 3,
507
+ 'optional' => true,
508
+ 'explicit' => true
509
+ ) + $this->Extensions
510
+ )
511
+ );
512
+
513
+ $this->Certificate = array(
514
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
515
+ 'children' => array(
516
+ 'tbsCertificate' => $TBSCertificate,
517
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
518
+ 'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
519
+ )
520
+ );
521
+
522
+ $this->KeyUsage = array(
523
+ 'type' => FILE_ASN1_TYPE_BIT_STRING,
524
+ 'mapping' => array(
525
+ 'digitalSignature',
526
+ 'nonRepudiation',
527
+ 'keyEncipherment',
528
+ 'dataEncipherment',
529
+ 'keyAgreement',
530
+ 'keyCertSign',
531
+ 'cRLSign',
532
+ 'encipherOnly',
533
+ 'decipherOnly'
534
+ )
535
+ );
536
+
537
+ $this->BasicConstraints = array(
538
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
539
+ 'children' => array(
540
+ 'cA' => array(
541
+ 'type' => FILE_ASN1_TYPE_BOOLEAN,
542
+ 'optional' => true,
543
+ 'default' => false
544
+ ),
545
+ 'pathLenConstraint' => array(
546
+ 'type' => FILE_ASN1_TYPE_INTEGER,
547
+ 'optional' => true
548
+ )
549
+ )
550
+ );
551
+
552
+ $this->KeyIdentifier = array('type' => FILE_ASN1_TYPE_OCTET_STRING);
553
+
554
+ $OrganizationalUnitNames = array(
555
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
556
+ 'min' => 1,
557
+ 'max' => 4, // ub-organizational-units
558
+ 'children' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
559
+ );
560
+
561
+ $PersonalName = array(
562
+ 'type' => FILE_ASN1_TYPE_SET,
563
+ 'children' => array(
564
+ 'surname' => array(
565
+ 'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
566
+ 'constant' => 0,
567
+ 'optional' => true,
568
+ 'implicit' => true
569
+ ),
570
+ 'given-name' => array(
571
+ 'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
572
+ 'constant' => 1,
573
+ 'optional' => true,
574
+ 'implicit' => true
575
+ ),
576
+ 'initials' => array(
577
+ 'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
578
+ 'constant' => 2,
579
+ 'optional' => true,
580
+ 'implicit' => true
581
+ ),
582
+ 'generation-qualifier' => array(
583
+ 'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
584
+ 'constant' => 3,
585
+ 'optional' => true,
586
+ 'implicit' => true
587
+ )
588
+ )
589
+ );
590
+
591
+ $NumericUserIdentifier = array('type' => FILE_ASN1_TYPE_NUMERIC_STRING);
592
+
593
+ $OrganizationName = array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING);
594
+
595
+ $PrivateDomainName = array(
596
+ 'type' => FILE_ASN1_TYPE_CHOICE,
597
+ 'children' => array(
598
+ 'numeric' => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING),
599
+ 'printable' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
600
+ )
601
+ );
602
+
603
+ $TerminalIdentifier = array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING);
604
+
605
+ $NetworkAddress = array('type' => FILE_ASN1_TYPE_NUMERIC_STRING);
606
+
607
+ $AdministrationDomainName = array(
608
+ 'type' => FILE_ASN1_TYPE_CHOICE,
609
+ // if class isn't present it's assumed to be FILE_ASN1_CLASS_UNIVERSAL or
610
+ // (if constant is present) FILE_ASN1_CLASS_CONTEXT_SPECIFIC
611
+ 'class' => FILE_ASN1_CLASS_APPLICATION,
612
+ 'cast' => 2,
613
+ 'children' => array(
614
+ 'numeric' => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING),
615
+ 'printable' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
616
+ )
617
+ );
618
+
619
+ $CountryName = array(
620
+ 'type' => FILE_ASN1_TYPE_CHOICE,
621
+ // if class isn't present it's assumed to be FILE_ASN1_CLASS_UNIVERSAL or
622
+ // (if constant is present) FILE_ASN1_CLASS_CONTEXT_SPECIFIC
623
+ 'class' => FILE_ASN1_CLASS_APPLICATION,
624
+ 'cast' => 1,
625
+ 'children' => array(
626
+ 'x121-dcc-code' => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING),
627
+ 'iso-3166-alpha2-code' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
628
+ )
629
+ );
630
+
631
+ $AnotherName = array(
632
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
633
+ 'children' => array(
634
+ 'type-id' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
635
+ 'value' => array(
636
+ 'type' => FILE_ASN1_TYPE_ANY,
637
+ 'constant' => 0,
638
+ 'optional' => true,
639
+ 'explicit' => true
640
+ )
641
+ )
642
+ );
643
+
644
+ $ExtensionAttribute = array(
645
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
646
+ 'children' => array(
647
+ 'extension-attribute-type' => array(
648
+ 'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
649
+ 'constant' => 0,
650
+ 'optional' => true,
651
+ 'implicit' => true
652
+ ),
653
+ 'extension-attribute-value' => array(
654
+ 'type' => FILE_ASN1_TYPE_ANY,
655
+ 'constant' => 1,
656
+ 'optional' => true,
657
+ 'explicit' => true
658
+ )
659
+ )
660
+ );
661
+
662
+ $ExtensionAttributes = array(
663
+ 'type' => FILE_ASN1_TYPE_SET,
664
+ 'min' => 1,
665
+ 'max' => 256, // ub-extension-attributes
666
+ 'children' => $ExtensionAttribute
667
+ );
668
+
669
+ $BuiltInDomainDefinedAttribute = array(
670
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
671
+ 'children' => array(
672
+ 'type' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING),
673
+ 'value' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
674
+ )
675
+ );
676
+
677
+ $BuiltInDomainDefinedAttributes = array(
678
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
679
+ 'min' => 1,
680
+ 'max' => 4, // ub-domain-defined-attributes
681
+ 'children' => $BuiltInDomainDefinedAttribute
682
+ );
683
+
684
+ $BuiltInStandardAttributes = array(
685
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
686
+ 'children' => array(
687
+ 'country-name' => array('optional' => true) + $CountryName,
688
+ 'administration-domain-name' => array('optional' => true) + $AdministrationDomainName,
689
+ 'network-address' => array(
690
+ 'constant' => 0,
691
+ 'optional' => true,
692
+ 'implicit' => true
693
+ ) + $NetworkAddress,
694
+ 'terminal-identifier' => array(
695
+ 'constant' => 1,
696
+ 'optional' => true,
697
+ 'implicit' => true
698
+ ) + $TerminalIdentifier,
699
+ 'private-domain-name' => array(
700
+ 'constant' => 2,
701
+ 'optional' => true,
702
+ 'explicit' => true
703
+ ) + $PrivateDomainName,
704
+ 'organization-name' => array(
705
+ 'constant' => 3,
706
+ 'optional' => true,
707
+ 'implicit' => true
708
+ ) + $OrganizationName,
709
+ 'numeric-user-identifier' => array(
710
+ 'constant' => 4,
711
+ 'optional' => true,
712
+ 'implicit' => true
713
+ ) + $NumericUserIdentifier,
714
+ 'personal-name' => array(
715
+ 'constant' => 5,
716
+ 'optional' => true,
717
+ 'implicit' => true
718
+ ) + $PersonalName,
719
+ 'organizational-unit-names' => array(
720
+ 'constant' => 6,
721
+ 'optional' => true,
722
+ 'implicit' => true
723
+ ) + $OrganizationalUnitNames
724
+ )
725
+ );
726
+
727
+ $ORAddress = array(
728
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
729
+ 'children' => array(
730
+ 'built-in-standard-attributes' => $BuiltInStandardAttributes,
731
+ 'built-in-domain-defined-attributes' => array('optional' => true) + $BuiltInDomainDefinedAttributes,
732
+ 'extension-attributes' => array('optional' => true) + $ExtensionAttributes
733
+ )
734
+ );
735
+
736
+ $EDIPartyName = array(
737
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
738
+ 'children' => array(
739
+ 'nameAssigner' => array(
740
+ 'constant' => 0,
741
+ 'optional' => true,
742
+ 'implicit' => true
743
+ ) + $this->DirectoryString,
744
+ // partyName is technically required but File_ASN1 doesn't currently support non-optional constants and
745
+ // setting it to optional gets the job done in any event.
746
+ 'partyName' => array(
747
+ 'constant' => 1,
748
+ 'optional' => true,
749
+ 'implicit' => true
750
+ ) + $this->DirectoryString
751
+ )
752
+ );
753
+
754
+ $GeneralName = array(
755
+ 'type' => FILE_ASN1_TYPE_CHOICE,
756
+ 'children' => array(
757
+ 'otherName' => array(
758
+ 'constant' => 0,
759
+ 'optional' => true,
760
+ 'implicit' => true
761
+ ) + $AnotherName,
762
+ 'rfc822Name' => array(
763
+ 'type' => FILE_ASN1_TYPE_IA5_STRING,
764
+ 'constant' => 1,
765
+ 'optional' => true,
766
+ 'implicit' => true
767
+ ),
768
+ 'dNSName' => array(
769
+ 'type' => FILE_ASN1_TYPE_IA5_STRING,
770
+ 'constant' => 2,
771
+ 'optional' => true,
772
+ 'implicit' => true
773
+ ),
774
+ 'x400Address' => array(
775
+ 'constant' => 3,
776
+ 'optional' => true,
777
+ 'implicit' => true
778
+ ) + $ORAddress,
779
+ 'directoryName' => array(
780
+ 'constant' => 4,
781
+ 'optional' => true,
782
+ 'explicit' => true
783
+ ) + $this->Name,
784
+ 'ediPartyName' => array(
785
+ 'constant' => 5,
786
+ 'optional' => true,
787
+ 'implicit' => true
788
+ ) + $EDIPartyName,
789
+ 'uniformResourceIdentifier' => array(
790
+ 'type' => FILE_ASN1_TYPE_IA5_STRING,
791
+ 'constant' => 6,
792
+ 'optional' => true,
793
+ 'implicit' => true
794
+ ),
795
+ 'iPAddress' => array(
796
+ 'type' => FILE_ASN1_TYPE_OCTET_STRING,
797
+ 'constant' => 7,
798
+ 'optional' => true,
799
+ 'implicit' => true
800
+ ),
801
+ 'registeredID' => array(
802
+ 'type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER,
803
+ 'constant' => 8,
804
+ 'optional' => true,
805
+ 'implicit' => true
806
+ )
807
+ )
808
+ );
809
+
810
+ $GeneralNames = array(
811
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
812
+ 'min' => 1,
813
+ 'max' => -1,
814
+ 'children' => $GeneralName
815
+ );
816
+
817
+ $this->IssuerAltName = $GeneralNames;
818
+
819
+ $ReasonFlags = array(
820
+ 'type' => FILE_ASN1_TYPE_BIT_STRING,
821
+ 'mapping' => array(
822
+ 'unused',
823
+ 'keyCompromise',
824
+ 'cACompromise',
825
+ 'affiliationChanged',
826
+ 'superseded',
827
+ 'cessationOfOperation',
828
+ 'certificateHold',
829
+ 'privilegeWithdrawn',
830
+ 'aACompromise'
831
+ )
832
+ );
833
+
834
+ $DistributionPointName = array(
835
+ 'type' => FILE_ASN1_TYPE_CHOICE,
836
+ 'children' => array(
837
+ 'fullName' => array(
838
+ 'constant' => 0,
839
+ 'optional' => true,
840
+ 'implicit' => true
841
+ ) + $GeneralNames,
842
+ 'nameRelativeToCRLIssuer' => array(
843
+ 'constant' => 1,
844
+ 'optional' => true,
845
+ 'implicit' => true
846
+ ) + $this->RelativeDistinguishedName
847
+ )
848
+ );
849
+
850
+ $DistributionPoint = array(
851
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
852
+ 'children' => array(
853
+ 'distributionPoint' => array(
854
+ 'constant' => 0,
855
+ 'optional' => true,
856
+ 'explicit' => true
857
+ ) + $DistributionPointName,
858
+ 'reasons' => array(
859
+ 'constant' => 1,
860
+ 'optional' => true,
861
+ 'implicit' => true
862
+ ) + $ReasonFlags,
863
+ 'cRLIssuer' => array(
864
+ 'constant' => 2,
865
+ 'optional' => true,
866
+ 'implicit' => true
867
+ ) + $GeneralNames
868
+ )
869
+ );
870
+
871
+ $this->CRLDistributionPoints = array(
872
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
873
+ 'min' => 1,
874
+ 'max' => -1,
875
+ 'children' => $DistributionPoint
876
+ );
877
+
878
+ $this->AuthorityKeyIdentifier = array(
879
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
880
+ 'children' => array(
881
+ 'keyIdentifier' => array(
882
+ 'constant' => 0,
883
+ 'optional' => true,
884
+ 'implicit' => true
885
+ ) + $this->KeyIdentifier,
886
+ 'authorityCertIssuer' => array(
887
+ 'constant' => 1,
888
+ 'optional' => true,
889
+ 'implicit' => true
890
+ ) + $GeneralNames,
891
+ 'authorityCertSerialNumber' => array(
892
+ 'constant' => 2,
893
+ 'optional' => true,
894
+ 'implicit' => true
895
+ ) + $CertificateSerialNumber
896
+ )
897
+ );
898
+
899
+ $PolicyQualifierId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
900
+
901
+ $PolicyQualifierInfo = array(
902
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
903
+ 'children' => array(
904
+ 'policyQualifierId' => $PolicyQualifierId,
905
+ 'qualifier' => array('type' => FILE_ASN1_TYPE_ANY)
906
+ )
907
+ );
908
+
909
+ $CertPolicyId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
910
+
911
+ $PolicyInformation = array(
912
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
913
+ 'children' => array(
914
+ 'policyIdentifier' => $CertPolicyId,
915
+ 'policyQualifiers' => array(
916
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
917
+ 'min' => 0,
918
+ 'max' => -1,
919
+ 'optional' => true,
920
+ 'children' => $PolicyQualifierInfo
921
+ )
922
+ )
923
+ );
924
+
925
+ $this->CertificatePolicies = array(
926
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
927
+ 'min' => 1,
928
+ 'max' => -1,
929
+ 'children' => $PolicyInformation
930
+ );
931
+
932
+ $this->PolicyMappings = array(
933
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
934
+ 'min' => 1,
935
+ 'max' => -1,
936
+ 'children' => array(
937
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
938
+ 'children' => array(
939
+ 'issuerDomainPolicy' => $CertPolicyId,
940
+ 'subjectDomainPolicy' => $CertPolicyId
941
+ )
942
+ )
943
+ );
944
+
945
+ $KeyPurposeId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
946
+
947
+ $this->ExtKeyUsageSyntax = array(
948
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
949
+ 'min' => 1,
950
+ 'max' => -1,
951
+ 'children' => $KeyPurposeId
952
+ );
953
+
954
+ $AccessDescription = array(
955
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
956
+ 'children' => array(
957
+ 'accessMethod' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
958
+ 'accessLocation' => $GeneralName
959
+ )
960
+ );
961
+
962
+ $this->AuthorityInfoAccessSyntax = array(
963
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
964
+ 'min' => 1,
965
+ 'max' => -1,
966
+ 'children' => $AccessDescription
967
+ );
968
+
969
+ $this->SubjectAltName = $GeneralNames;
970
+
971
+ $this->PrivateKeyUsagePeriod = array(
972
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
973
+ 'children' => array(
974
+ 'notBefore' => array(
975
+ 'constant' => 0,
976
+ 'optional' => true,
977
+ 'implicit' => true,
978
+ 'type' => FILE_ASN1_TYPE_GENERALIZED_TIME),
979
+ 'notAfter' => array(
980
+ 'constant' => 1,
981
+ 'optional' => true,
982
+ 'implicit' => true,
983
+ 'type' => FILE_ASN1_TYPE_GENERALIZED_TIME)
984
+ )
985
+ );
986
+
987
+ $BaseDistance = array('type' => FILE_ASN1_TYPE_INTEGER);
988
+
989
+ $GeneralSubtree = array(
990
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
991
+ 'children' => array(
992
+ 'base' => $GeneralName,
993
+ 'minimum' => array(
994
+ 'constant' => 0,
995
+ 'optional' => true,
996
+ 'implicit' => true,
997
+ 'default' => new Math_BigInteger(0)
998
+ ) + $BaseDistance,
999
+ 'maximum' => array(
1000
+ 'constant' => 1,
1001
+ 'optional' => true,
1002
+ 'implicit' => true,
1003
+ ) + $BaseDistance
1004
+ )
1005
+ );
1006
+
1007
+ $GeneralSubtrees = array(
1008
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1009
+ 'min' => 1,
1010
+ 'max' => -1,
1011
+ 'children' => $GeneralSubtree
1012
+ );
1013
+
1014
+ $this->NameConstraints = array(
1015
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1016
+ 'children' => array(
1017
+ 'permittedSubtrees' => array(
1018
+ 'constant' => 0,
1019
+ 'optional' => true,
1020
+ 'implicit' => true
1021
+ ) + $GeneralSubtrees,
1022
+ 'excludedSubtrees' => array(
1023
+ 'constant' => 1,
1024
+ 'optional' => true,
1025
+ 'implicit' => true
1026
+ ) + $GeneralSubtrees
1027
+ )
1028
+ );
1029
+
1030
+ $this->CPSuri = array('type' => FILE_ASN1_TYPE_IA5_STRING);
1031
+
1032
+ $DisplayText = array(
1033
+ 'type' => FILE_ASN1_TYPE_CHOICE,
1034
+ 'children' => array(
1035
+ 'ia5String' => array('type' => FILE_ASN1_TYPE_IA5_STRING),
1036
+ 'visibleString' => array('type' => FILE_ASN1_TYPE_VISIBLE_STRING),
1037
+ 'bmpString' => array('type' => FILE_ASN1_TYPE_BMP_STRING),
1038
+ 'utf8String' => array('type' => FILE_ASN1_TYPE_UTF8_STRING)
1039
+ )
1040
+ );
1041
+
1042
+ $NoticeReference = array(
1043
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1044
+ 'children' => array(
1045
+ 'organization' => $DisplayText,
1046
+ 'noticeNumbers' => array(
1047
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1048
+ 'min' => 1,
1049
+ 'max' => 200,
1050
+ 'children' => array('type' => FILE_ASN1_TYPE_INTEGER)
1051
+ )
1052
+ )
1053
+ );
1054
+
1055
+ $this->UserNotice = array(
1056
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1057
+ 'children' => array(
1058
+ 'noticeRef' => array(
1059
+ 'optional' => true,
1060
+ 'implicit' => true
1061
+ ) + $NoticeReference,
1062
+ 'explicitText' => array(
1063
+ 'optional' => true,
1064
+ 'implicit' => true
1065
+ ) + $DisplayText
1066
+ )
1067
+ );
1068
+
1069
+ // mapping is from <http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html>
1070
+ $this->netscape_cert_type = array(
1071
+ 'type' => FILE_ASN1_TYPE_BIT_STRING,
1072
+ 'mapping' => array(
1073
+ 'SSLClient',
1074
+ 'SSLServer',
1075
+ 'Email',
1076
+ 'ObjectSigning',
1077
+ 'Reserved',
1078
+ 'SSLCA',
1079
+ 'EmailCA',
1080
+ 'ObjectSigningCA'
1081
+ )
1082
+ );
1083
+
1084
+ $this->netscape_comment = array('type' => FILE_ASN1_TYPE_IA5_STRING);
1085
+ $this->netscape_ca_policy_url = array('type' => FILE_ASN1_TYPE_IA5_STRING);
1086
+
1087
+ // attribute is used in RFC2986 but we're using the RFC5280 definition
1088
+
1089
+ $Attribute = array(
1090
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1091
+ 'children' => array(
1092
+ 'type' => $AttributeType,
1093
+ 'value'=> array(
1094
+ 'type' => FILE_ASN1_TYPE_SET,
1095
+ 'min' => 1,
1096
+ 'max' => -1,
1097
+ 'children' => $this->AttributeValue
1098
+ )
1099
+ )
1100
+ );
1101
+
1102
+ $this->SubjectDirectoryAttributes = array(
1103
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1104
+ 'min' => 1,
1105
+ 'max' => -1,
1106
+ 'children' => $Attribute
1107
+ );
1108
+
1109
+ // adapted from <http://tools.ietf.org/html/rfc2986>
1110
+
1111
+ $Attributes = array(
1112
+ 'type' => FILE_ASN1_TYPE_SET,
1113
+ 'min' => 1,
1114
+ 'max' => -1,
1115
+ 'children' => $Attribute
1116
+ );
1117
+
1118
+ $CertificationRequestInfo = array(
1119
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1120
+ 'children' => array(
1121
+ 'version' => array(
1122
+ 'type' => FILE_ASN1_TYPE_INTEGER,
1123
+ 'mapping' => array('v1')
1124
+ ),
1125
+ 'subject' => $this->Name,
1126
+ 'subjectPKInfo' => $SubjectPublicKeyInfo,
1127
+ 'attributes' => array(
1128
+ 'constant' => 0,
1129
+ 'optional' => true,
1130
+ 'implicit' => true
1131
+ ) + $Attributes,
1132
+ )
1133
+ );
1134
+
1135
+ $this->CertificationRequest = array(
1136
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1137
+ 'children' => array(
1138
+ 'certificationRequestInfo' => $CertificationRequestInfo,
1139
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
1140
+ 'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
1141
+ )
1142
+ );
1143
+
1144
+ $RevokedCertificate = array(
1145
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1146
+ 'children' => array(
1147
+ 'userCertificate' => $CertificateSerialNumber,
1148
+ 'revocationDate' => $Time,
1149
+ 'crlEntryExtensions' => array(
1150
+ 'optional' => true
1151
+ ) + $this->Extensions
1152
+ )
1153
+ );
1154
+
1155
+ $TBSCertList = array(
1156
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1157
+ 'children' => array(
1158
+ 'version' => array(
1159
+ 'optional' => true,
1160
+ 'default' => 'v1'
1161
+ ) + $Version,
1162
+ 'signature' => $AlgorithmIdentifier,
1163
+ 'issuer' => $this->Name,
1164
+ 'thisUpdate' => $Time,
1165
+ 'nextUpdate' => array(
1166
+ 'optional' => true
1167
+ ) + $Time,
1168
+ 'revokedCertificates' => array(
1169
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1170
+ 'optional' => true,
1171
+ 'min' => 0,
1172
+ 'max' => -1,
1173
+ 'children' => $RevokedCertificate
1174
+ ),
1175
+ 'crlExtensions' => array(
1176
+ 'constant' => 0,
1177
+ 'optional' => true,
1178
+ 'explicit' => true
1179
+ ) + $this->Extensions
1180
+ )
1181
+ );
1182
+
1183
+ $this->CertificateList = array(
1184
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1185
+ 'children' => array(
1186
+ 'tbsCertList' => $TBSCertList,
1187
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
1188
+ 'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
1189
+ )
1190
+ );
1191
+
1192
+ $this->CRLNumber = array('type' => FILE_ASN1_TYPE_INTEGER);
1193
+
1194
+ $this->CRLReason = array('type' => FILE_ASN1_TYPE_ENUMERATED,
1195
+ 'mapping' => array(
1196
+ 'unspecified',
1197
+ 'keyCompromise',
1198
+ 'cACompromise',
1199
+ 'affiliationChanged',
1200
+ 'superseded',
1201
+ 'cessationOfOperation',
1202
+ 'certificateHold',
1203
+ // Value 7 is not used.
1204
+ 8 => 'removeFromCRL',
1205
+ 'privilegeWithdrawn',
1206
+ 'aACompromise'
1207
+ )
1208
+ );
1209
+
1210
+ $this->IssuingDistributionPoint = array('type' => FILE_ASN1_TYPE_SEQUENCE,
1211
+ 'children' => array(
1212
+ 'distributionPoint' => array(
1213
+ 'constant' => 0,
1214
+ 'optional' => true,
1215
+ 'explicit' => true
1216
+ ) + $DistributionPointName,
1217
+ 'onlyContainsUserCerts' => array(
1218
+ 'type' => FILE_ASN1_TYPE_BOOLEAN,
1219
+ 'constant' => 1,
1220
+ 'optional' => true,
1221
+ 'default' => false,
1222
+ 'implicit' => true
1223
+ ),
1224
+ 'onlyContainsCACerts' => array(
1225
+ 'type' => FILE_ASN1_TYPE_BOOLEAN,
1226
+ 'constant' => 2,
1227
+ 'optional' => true,
1228
+ 'default' => false,
1229
+ 'implicit' => true
1230
+ ),
1231
+ 'onlySomeReasons' => array(
1232
+ 'constant' => 3,
1233
+ 'optional' => true,
1234
+ 'implicit' => true
1235
+ ) + $ReasonFlags,
1236
+ 'indirectCRL' => array(
1237
+ 'type' => FILE_ASN1_TYPE_BOOLEAN,
1238
+ 'constant' => 4,
1239
+ 'optional' => true,
1240
+ 'default' => false,
1241
+ 'implicit' => true
1242
+ ),
1243
+ 'onlyContainsAttributeCerts' => array(
1244
+ 'type' => FILE_ASN1_TYPE_BOOLEAN,
1245
+ 'constant' => 5,
1246
+ 'optional' => true,
1247
+ 'default' => false,
1248
+ 'implicit' => true
1249
+ )
1250
+ )
1251
+ );
1252
+
1253
+ $this->InvalidityDate = array('type' => FILE_ASN1_TYPE_GENERALIZED_TIME);
1254
+
1255
+ $this->CertificateIssuer = $GeneralNames;
1256
+
1257
+ $this->HoldInstructionCode = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
1258
+
1259
+ $PublicKeyAndChallenge = array(
1260
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1261
+ 'children' => array(
1262
+ 'spki' => $SubjectPublicKeyInfo,
1263
+ 'challenge' => array('type' => FILE_ASN1_TYPE_IA5_STRING)
1264
+ )
1265
+ );
1266
+
1267
+ $this->SignedPublicKeyAndChallenge = array(
1268
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1269
+ 'children' => array(
1270
+ 'publicKeyAndChallenge' => $PublicKeyAndChallenge,
1271
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
1272
+ 'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
1273
+ )
1274
+ );
1275
+
1276
+ $this->PostalAddress = array(
1277
+ 'type' => FILE_ASN1_TYPE_SEQUENCE,
1278
+ 'optional' => true,
1279
+ 'min' => 1,
1280
+ 'max' => -1,
1281
+ 'children' => $this->DirectoryString
1282
+ );
1283
+
1284
+ // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
1285
+ $this->oids = array(
1286
+ '1.3.6.1.5.5.7' => 'id-pkix',
1287
+ '1.3.6.1.5.5.7.1' => 'id-pe',
1288
+ '1.3.6.1.5.5.7.2' => 'id-qt',
1289
+ '1.3.6.1.5.5.7.3' => 'id-kp',
1290
+ '1.3.6.1.5.5.7.48' => 'id-ad',
1291
+ '1.3.6.1.5.5.7.2.1' => 'id-qt-cps',
1292
+ '1.3.6.1.5.5.7.2.2' => 'id-qt-unotice',
1293
+ '1.3.6.1.5.5.7.48.1' =>'id-ad-ocsp',
1294
+ '1.3.6.1.5.5.7.48.2' => 'id-ad-caIssuers',
1295
+ '1.3.6.1.5.5.7.48.3' => 'id-ad-timeStamping',
1296
+ '1.3.6.1.5.5.7.48.5' => 'id-ad-caRepository',
1297
+ '2.5.4' => 'id-at',
1298
+ '2.5.4.41' => 'id-at-name',
1299
+ '2.5.4.4' => 'id-at-surname',
1300
+ '2.5.4.42' => 'id-at-givenName',
1301
+ '2.5.4.43' => 'id-at-initials',
1302
+ '2.5.4.44' => 'id-at-generationQualifier',
1303
+ '2.5.4.3' => 'id-at-commonName',
1304
+ '2.5.4.7' => 'id-at-localityName',
1305
+ '2.5.4.8' => 'id-at-stateOrProvinceName',
1306
+ '2.5.4.10' => 'id-at-organizationName',
1307
+ '2.5.4.11' => 'id-at-organizationalUnitName',
1308
+ '2.5.4.12' => 'id-at-title',
1309
+ '2.5.4.13' => 'id-at-description',
1310
+ '2.5.4.46' => 'id-at-dnQualifier',
1311
+ '2.5.4.6' => 'id-at-countryName',
1312
+ '2.5.4.5' => 'id-at-serialNumber',
1313
+ '2.5.4.65' => 'id-at-pseudonym',
1314
+ '2.5.4.17' => 'id-at-postalCode',
1315
+ '2.5.4.9' => 'id-at-streetAddress',
1316
+ '2.5.4.45' => 'id-at-uniqueIdentifier',
1317
+ '2.5.4.72' => 'id-at-role',
1318
+ '2.5.4.16' => 'id-at-postalAddress',
1319
+
1320
+ '0.9.2342.19200300.100.1.25' => 'id-domainComponent',
1321
+ '1.2.840.113549.1.9' => 'pkcs-9',
1322
+ '1.2.840.113549.1.9.1' => 'pkcs-9-at-emailAddress',
1323
+ '2.5.29' => 'id-ce',
1324
+ '2.5.29.35' => 'id-ce-authorityKeyIdentifier',
1325
+ '2.5.29.14' => 'id-ce-subjectKeyIdentifier',
1326
+ '2.5.29.15' => 'id-ce-keyUsage',
1327
+ '2.5.29.16' => 'id-ce-privateKeyUsagePeriod',
1328
+ '2.5.29.32' => 'id-ce-certificatePolicies',
1329
+ '2.5.29.32.0' => 'anyPolicy',
1330
+
1331
+ '2.5.29.33' => 'id-ce-policyMappings',
1332
+ '2.5.29.17' => 'id-ce-subjectAltName',
1333
+ '2.5.29.18' => 'id-ce-issuerAltName',
1334
+ '2.5.29.9' => 'id-ce-subjectDirectoryAttributes',
1335
+ '2.5.29.19' => 'id-ce-basicConstraints',
1336
+ '2.5.29.30' => 'id-ce-nameConstraints',
1337
+ '2.5.29.36' => 'id-ce-policyConstraints',
1338
+ '2.5.29.31' => 'id-ce-cRLDistributionPoints',
1339
+ '2.5.29.37' => 'id-ce-extKeyUsage',
1340
+ '2.5.29.37.0' => 'anyExtendedKeyUsage',
1341
+ '1.3.6.1.5.5.7.3.1' => 'id-kp-serverAuth',
1342
+ '1.3.6.1.5.5.7.3.2' => 'id-kp-clientAuth',
1343
+ '1.3.6.1.5.5.7.3.3' => 'id-kp-codeSigning',
1344
+ '1.3.6.1.5.5.7.3.4' => 'id-kp-emailProtection',
1345
+ '1.3.6.1.5.5.7.3.8' => 'id-kp-timeStamping',
1346
+ '1.3.6.1.5.5.7.3.9' => 'id-kp-OCSPSigning',
1347
+ '2.5.29.54' => 'id-ce-inhibitAnyPolicy',
1348
+ '2.5.29.46' => 'id-ce-freshestCRL',
1349
+ '1.3.6.1.5.5.7.1.1' => 'id-pe-authorityInfoAccess',
1350
+ '1.3.6.1.5.5.7.1.11' => 'id-pe-subjectInfoAccess',
1351
+ '2.5.29.20' => 'id-ce-cRLNumber',
1352
+ '2.5.29.28' => 'id-ce-issuingDistributionPoint',
1353
+ '2.5.29.27' => 'id-ce-deltaCRLIndicator',
1354
+ '2.5.29.21' => 'id-ce-cRLReasons',
1355
+ '2.5.29.29' => 'id-ce-certificateIssuer',
1356
+ '2.5.29.23' => 'id-ce-holdInstructionCode',
1357
+ '1.2.840.10040.2' => 'holdInstruction',
1358
+ '1.2.840.10040.2.1' => 'id-holdinstruction-none',
1359
+ '1.2.840.10040.2.2' => 'id-holdinstruction-callissuer',
1360
+ '1.2.840.10040.2.3' => 'id-holdinstruction-reject',
1361
+ '2.5.29.24' => 'id-ce-invalidityDate',
1362
+
1363
+ '1.2.840.113549.2.2' => 'md2',
1364
+ '1.2.840.113549.2.5' => 'md5',
1365
+ '1.3.14.3.2.26' => 'id-sha1',
1366
+ '1.2.840.10040.4.1' => 'id-dsa',
1367
+ '1.2.840.10040.4.3' => 'id-dsa-with-sha1',
1368
+ '1.2.840.113549.1.1' => 'pkcs-1',
1369
+ '1.2.840.113549.1.1.1' => 'rsaEncryption',
1370
+ '1.2.840.113549.1.1.2' => 'md2WithRSAEncryption',
1371
+ '1.2.840.113549.1.1.4' => 'md5WithRSAEncryption',
1372
+ '1.2.840.113549.1.1.5' => 'sha1WithRSAEncryption',
1373
+ '1.2.840.10046.2.1' => 'dhpublicnumber',
1374
+ '2.16.840.1.101.2.1.1.22' => 'id-keyExchangeAlgorithm',
1375
+ '1.2.840.10045' => 'ansi-X9-62',
1376
+ '1.2.840.10045.4' => 'id-ecSigType',
1377
+ '1.2.840.10045.4.1' => 'ecdsa-with-SHA1',
1378
+ '1.2.840.10045.1' => 'id-fieldType',
1379
+ '1.2.840.10045.1.1' => 'prime-field',
1380
+ '1.2.840.10045.1.2' => 'characteristic-two-field',
1381
+ '1.2.840.10045.1.2.3' => 'id-characteristic-two-basis',
1382
+ '1.2.840.10045.1.2.3.1' => 'gnBasis',
1383
+ '1.2.840.10045.1.2.3.2' => 'tpBasis',
1384
+ '1.2.840.10045.1.2.3.3' => 'ppBasis',
1385
+ '1.2.840.10045.2' => 'id-publicKeyType',
1386
+ '1.2.840.10045.2.1' => 'id-ecPublicKey',
1387
+ '1.2.840.10045.3' => 'ellipticCurve',
1388
+ '1.2.840.10045.3.0' => 'c-TwoCurve',
1389
+ '1.2.840.10045.3.0.1' => 'c2pnb163v1',
1390
+ '1.2.840.10045.3.0.2' => 'c2pnb163v2',
1391
+ '1.2.840.10045.3.0.3' => 'c2pnb163v3',
1392
+ '1.2.840.10045.3.0.4' => 'c2pnb176w1',
1393
+ '1.2.840.10045.3.0.5' => 'c2pnb191v1',
1394
+ '1.2.840.10045.3.0.6' => 'c2pnb191v2',
1395
+ '1.2.840.10045.3.0.7' => 'c2pnb191v3',
1396
+ '1.2.840.10045.3.0.8' => 'c2pnb191v4',
1397
+ '1.2.840.10045.3.0.9' => 'c2pnb191v5',
1398
+ '1.2.840.10045.3.0.10' => 'c2pnb208w1',
1399
+ '1.2.840.10045.3.0.11' => 'c2pnb239v1',
1400
+ '1.2.840.10045.3.0.12' => 'c2pnb239v2',
1401
+ '1.2.840.10045.3.0.13' => 'c2pnb239v3',
1402
+ '1.2.840.10045.3.0.14' => 'c2pnb239v4',
1403
+ '1.2.840.10045.3.0.15' => 'c2pnb239v5',
1404
+ '1.2.840.10045.3.0.16' => 'c2pnb272w1',
1405
+ '1.2.840.10045.3.0.17' => 'c2pnb304w1',
1406
+ '1.2.840.10045.3.0.18' => 'c2pnb359v1',
1407
+ '1.2.840.10045.3.0.19' => 'c2pnb368w1',
1408
+ '1.2.840.10045.3.0.20' => 'c2pnb431r1',
1409
+ '1.2.840.10045.3.1' => 'primeCurve',
1410
+ '1.2.840.10045.3.1.1' => 'prime192v1',
1411
+ '1.2.840.10045.3.1.2' => 'prime192v2',
1412
+ '1.2.840.10045.3.1.3' => 'prime192v3',
1413
+ '1.2.840.10045.3.1.4' => 'prime239v1',
1414
+ '1.2.840.10045.3.1.5' => 'prime239v2',
1415
+ '1.2.840.10045.3.1.6' => 'prime239v3',
1416
+ '1.2.840.10045.3.1.7' => 'prime256v1',
1417
+ '1.2.840.113549.1.1.7' => 'id-RSAES-OAEP',
1418
+ '1.2.840.113549.1.1.9' => 'id-pSpecified',
1419
+ '1.2.840.113549.1.1.10' => 'id-RSASSA-PSS',
1420
+ '1.2.840.113549.1.1.8' => 'id-mgf1',
1421
+ '1.2.840.113549.1.1.14' => 'sha224WithRSAEncryption',
1422
+ '1.2.840.113549.1.1.11' => 'sha256WithRSAEncryption',
1423
+ '1.2.840.113549.1.1.12' => 'sha384WithRSAEncryption',
1424
+ '1.2.840.113549.1.1.13' => 'sha512WithRSAEncryption',
1425
+ '2.16.840.1.101.3.4.2.4' => 'id-sha224',
1426
+ '2.16.840.1.101.3.4.2.1' => 'id-sha256',
1427
+ '2.16.840.1.101.3.4.2.2' => 'id-sha384',
1428
+ '2.16.840.1.101.3.4.2.3' => 'id-sha512',
1429
+ '1.2.643.2.2.4' => 'id-GostR3411-94-with-GostR3410-94',
1430
+ '1.2.643.2.2.3' => 'id-GostR3411-94-with-GostR3410-2001',
1431
+ '1.2.643.2.2.20' => 'id-GostR3410-2001',
1432
+ '1.2.643.2.2.19' => 'id-GostR3410-94',
1433
+ // Netscape Object Identifiers from "Netscape Certificate Extensions"
1434
+ '2.16.840.1.113730' => 'netscape',
1435
+ '2.16.840.1.113730.1' => 'netscape-cert-extension',
1436
+ '2.16.840.1.113730.1.1' => 'netscape-cert-type',
1437
+ '2.16.840.1.113730.1.13' => 'netscape-comment',
1438
+ '2.16.840.1.113730.1.8' => 'netscape-ca-policy-url',
1439
+ // the following are X.509 extensions not supported by phpseclib
1440
+ '1.3.6.1.5.5.7.1.12' => 'id-pe-logotype',
1441
+ '1.2.840.113533.7.65.0' => 'entrustVersInfo',
1442
+ '2.16.840.1.113733.1.6.9' => 'verisignPrivate',
1443
+ // for Certificate Signing Requests
1444
+ // see http://tools.ietf.org/html/rfc2985
1445
+ '1.2.840.113549.1.9.2' => 'pkcs-9-at-unstructuredName', // PKCS #9 unstructured name
1446
+ '1.2.840.113549.1.9.7' => 'pkcs-9-at-challengePassword', // Challenge password for certificate revocations
1447
+ '1.2.840.113549.1.9.14' => 'pkcs-9-at-extensionRequest' // Certificate extension request
1448
+ );
1449
+ }
1450
+
1451
+ /**
1452
+ * PHP4 compatible Default Constructor.
1453
+ *
1454
+ * @see self::__construct()
1455
+ * @access public
1456
+ */
1457
+ function File_X509()
1458
+ {
1459
+ $this->__construct();
1460
+ }
1461
+
1462
+ /**
1463
+ * Load X.509 certificate
1464
+ *
1465
+ * Returns an associative array describing the X.509 cert or a false if the cert failed to load
1466
+ *
1467
+ * @param string $cert
1468
+ * @param int $mode
1469
+ * @access public
1470
+ * @return mixed
1471
+ */
1472
+ function loadX509($cert, $mode = FILE_X509_FORMAT_AUTO_DETECT)
1473
+ {
1474
+ if (is_array($cert) && isset($cert['tbsCertificate'])) {
1475
+ unset($this->currentCert);
1476
+ unset($this->currentKeyIdentifier);
1477
+ $this->dn = $cert['tbsCertificate']['subject'];
1478
+ if (!isset($this->dn)) {
1479
+ return false;
1480
+ }
1481
+ $this->currentCert = $cert;
1482
+
1483
+ $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
1484
+ $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
1485
+
1486
+ unset($this->signatureSubject);
1487
+
1488
+ return $cert;
1489
+ }
1490
+
1491
+ $asn1 = new File_ASN1();
1492
+
1493
+ if ($mode != FILE_X509_FORMAT_DER) {
1494
+ $newcert = $this->_extractBER($cert);
1495
+ if ($mode == FILE_X509_FORMAT_PEM && $cert == $newcert) {
1496
+ return false;
1497
+ }
1498
+ $cert = $newcert;
1499
+ }
1500
+
1501
+ if ($cert === false) {
1502
+ $this->currentCert = false;
1503
+ return false;
1504
+ }
1505
+
1506
+ $asn1->loadOIDs($this->oids);
1507
+ $decoded = $asn1->decodeBER($cert);
1508
+
1509
+ if (!empty($decoded)) {
1510
+ $x509 = $asn1->asn1map($decoded[0], $this->Certificate);
1511
+ }
1512
+ if (!isset($x509) || $x509 === false) {
1513
+ $this->currentCert = false;
1514
+ return false;
1515
+ }
1516
+
1517
+ $this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
1518
+
1519
+ if ($this->_isSubArrayValid($x509, 'tbsCertificate/extensions')) {
1520
+ $this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
1521
+ }
1522
+ $this->_mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence', $asn1);
1523
+ $this->_mapInDNs($x509, 'tbsCertificate/subject/rdnSequence', $asn1);
1524
+
1525
+ $key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'];
1526
+ $key = $this->_reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key);
1527
+
1528
+ $this->currentCert = $x509;
1529
+ $this->dn = $x509['tbsCertificate']['subject'];
1530
+
1531
+ $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
1532
+ $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
1533
+
1534
+ return $x509;
1535
+ }
1536
+
1537
+ /**
1538
+ * Save X.509 certificate
1539
+ *
1540
+ * @param array $cert
1541
+ * @param int $format optional
1542
+ * @access public
1543
+ * @return string
1544
+ */
1545
+ function saveX509($cert, $format = FILE_X509_FORMAT_PEM)
1546
+ {
1547
+ if (!is_array($cert) || !isset($cert['tbsCertificate'])) {
1548
+ return false;
1549
+ }
1550
+
1551
+ switch (true) {
1552
+ // "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()"
1553
+ case !($algorithm = $this->_subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')):
1554
+ case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
1555
+ break;
1556
+ default:
1557
+ switch ($algorithm) {
1558
+ case 'rsaEncryption':
1559
+ $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
1560
+ = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])));
1561
+ /* "[For RSA keys] the parameters field MUST have ASN.1 type NULL for this algorithm identifier."
1562
+ -- https://tools.ietf.org/html/rfc3279#section-2.3.1
1563
+
1564
+ given that and the fact that RSA keys appear ot be the only key type for which the parameters field can be blank,
1565
+ it seems like perhaps the ASN.1 description ought not say the parameters field is OPTIONAL, but whatever.
1566
+ */
1567
+ $cert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = null;
1568
+ // https://tools.ietf.org/html/rfc3279#section-2.2.1
1569
+ $cert['signatureAlgorithm']['parameters'] = null;
1570
+ $cert['tbsCertificate']['signature']['parameters'] = null;
1571
+ }
1572
+ }
1573
+
1574
+ $asn1 = new File_ASN1();
1575
+ $asn1->loadOIDs($this->oids);
1576
+
1577
+ $filters = array();
1578
+ $type_utf8_string = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
1579
+ $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string;
1580
+ $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string;
1581
+ $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string;
1582
+ $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string;
1583
+ $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string;
1584
+ $filters['signatureAlgorithm']['parameters'] = $type_utf8_string;
1585
+ $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
1586
+ //$filters['policyQualifiers']['qualifier'] = $type_utf8_string;
1587
+ $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
1588
+ $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string;
1589
+
1590
+ /* in the case of policyQualifiers/qualifier, the type has to be FILE_ASN1_TYPE_IA5_STRING.
1591
+ FILE_ASN1_TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random
1592
+ characters.
1593
+ */
1594
+ $filters['policyQualifiers']['qualifier']
1595
+ = array('type' => FILE_ASN1_TYPE_IA5_STRING);
1596
+
1597
+ $asn1->loadFilters($filters);
1598
+
1599
+ $this->_mapOutExtensions($cert, 'tbsCertificate/extensions', $asn1);
1600
+ $this->_mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence', $asn1);
1601
+ $this->_mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence', $asn1);
1602
+
1603
+ $cert = $asn1->encodeDER($cert, $this->Certificate);
1604
+
1605
+ switch ($format) {
1606
+ case FILE_X509_FORMAT_DER:
1607
+ return $cert;
1608
+ // case FILE_X509_FORMAT_PEM:
1609
+ default:
1610
+ return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(base64_encode($cert), 64) . '-----END CERTIFICATE-----';
1611
+ }
1612
+ }
1613
+
1614
+ /**
1615
+ * Map extension values from octet string to extension-specific internal
1616
+ * format.
1617
+ *
1618
+ * @param array ref $root
1619
+ * @param string $path
1620
+ * @param object $asn1
1621
+ * @access private
1622
+ */
1623
+ function _mapInExtensions(&$root, $path, $asn1)
1624
+ {
1625
+ $extensions = &$this->_subArrayUnchecked($root, $path);
1626
+
1627
+ if ($extensions) {
1628
+ for ($i = 0; $i < count($extensions); $i++) {
1629
+ $id = $extensions[$i]['extnId'];
1630
+ $value = &$extensions[$i]['extnValue'];
1631
+ $value = base64_decode($value);
1632
+ $decoded = $asn1->decodeBER($value);
1633
+ /* [extnValue] contains the DER encoding of an ASN.1 value
1634
+ corresponding to the extension type identified by extnID */
1635
+ $map = $this->_getMapping($id);
1636
+ if (!is_bool($map)) {
1637
+ $mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => array($this, '_decodeIP')));
1638
+ $value = $mapped === false ? $decoded[0] : $mapped;
1639
+
1640
+ if ($id == 'id-ce-certificatePolicies') {
1641
+ for ($j = 0; $j < count($value); $j++) {
1642
+ if (!isset($value[$j]['policyQualifiers'])) {
1643
+ continue;
1644
+ }
1645
+ for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
1646
+ $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
1647
+ $map = $this->_getMapping($subid);
1648
+ $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier'];
1649
+ if ($map !== false) {
1650
+ $decoded = $asn1->decodeBER($subvalue);
1651
+ $mapped = $asn1->asn1map($decoded[0], $map);
1652
+ $subvalue = $mapped === false ? $decoded[0] : $mapped;
1653
+ }
1654
+ }
1655
+ }
1656
+ }
1657
+ } else {
1658
+ $value = base64_encode($value);
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+
1664
+ /**
1665
+ * Map extension values from extension-specific internal format to
1666
+ * octet string.
1667
+ *
1668
+ * @param array ref $root
1669
+ * @param string $path
1670
+ * @param object $asn1
1671
+ * @access private
1672
+ */
1673
+ function _mapOutExtensions(&$root, $path, $asn1)
1674
+ {
1675
+ $extensions = &$this->_subArray($root, $path);
1676
+
1677
+ if (is_array($extensions)) {
1678
+ $size = count($extensions);
1679
+ for ($i = 0; $i < $size; $i++) {
1680
+ if (is_object($extensions[$i]) && strtolower(get_class($extensions[$i])) == 'file_asn1_element') {
1681
+ continue;
1682
+ }
1683
+
1684
+ $id = $extensions[$i]['extnId'];
1685
+ $value = &$extensions[$i]['extnValue'];
1686
+
1687
+ switch ($id) {
1688
+ case 'id-ce-certificatePolicies':
1689
+ for ($j = 0; $j < count($value); $j++) {
1690
+ if (!isset($value[$j]['policyQualifiers'])) {
1691
+ continue;
1692
+ }
1693
+ for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
1694
+ $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
1695
+ $map = $this->_getMapping($subid);
1696
+ $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier'];
1697
+ if ($map !== false) {
1698
+ // by default File_ASN1 will try to render qualifier as a FILE_ASN1_TYPE_IA5_STRING since it's
1699
+ // actual type is FILE_ASN1_TYPE_ANY
1700
+ $subvalue = new File_ASN1_Element($asn1->encodeDER($subvalue, $map));
1701
+ }
1702
+ }
1703
+ }
1704
+ break;
1705
+ case 'id-ce-authorityKeyIdentifier': // use 00 as the serial number instead of an empty string
1706
+ if (isset($value['authorityCertSerialNumber'])) {
1707
+ if ($value['authorityCertSerialNumber']->toBytes() == '') {
1708
+ $temp = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0";
1709
+ $value['authorityCertSerialNumber'] = new File_ASN1_Element($temp);
1710
+ }
1711
+ }
1712
+ }
1713
+
1714
+ /* [extnValue] contains the DER encoding of an ASN.1 value
1715
+ corresponding to the extension type identified by extnID */
1716
+ $map = $this->_getMapping($id);
1717
+ if (is_bool($map)) {
1718
+ if (!$map) {
1719
+ user_error($id . ' is not a currently supported extension');
1720
+ unset($extensions[$i]);
1721
+ }
1722
+ } else {
1723
+ $temp = $asn1->encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
1724
+ $value = base64_encode($temp);
1725
+ }
1726
+ }
1727
+ }
1728
+ }
1729
+
1730
+ /**
1731
+ * Map attribute values from ANY type to attribute-specific internal
1732
+ * format.
1733
+ *
1734
+ * @param array ref $root
1735
+ * @param string $path
1736
+ * @param object $asn1
1737
+ * @access private
1738
+ */
1739
+ function _mapInAttributes(&$root, $path, $asn1)
1740
+ {
1741
+ $attributes = &$this->_subArray($root, $path);
1742
+
1743
+ if (is_array($attributes)) {
1744
+ for ($i = 0; $i < count($attributes); $i++) {
1745
+ $id = $attributes[$i]['type'];
1746
+ /* $value contains the DER encoding of an ASN.1 value
1747
+ corresponding to the attribute type identified by type */
1748
+ $map = $this->_getMapping($id);
1749
+ if (is_array($attributes[$i]['value'])) {
1750
+ $values = &$attributes[$i]['value'];
1751
+ for ($j = 0; $j < count($values); $j++) {
1752
+ $value = $asn1->encodeDER($values[$j], $this->AttributeValue);
1753
+ $decoded = $asn1->decodeBER($value);
1754
+ if (!is_bool($map)) {
1755
+ $mapped = $asn1->asn1map($decoded[0], $map);
1756
+ if ($mapped !== false) {
1757
+ $values[$j] = $mapped;
1758
+ }
1759
+ if ($id == 'pkcs-9-at-extensionRequest' && $this->_isSubArrayValid($values, $j)) {
1760
+ $this->_mapInExtensions($values, $j, $asn1);
1761
+ }
1762
+ } elseif ($map) {
1763
+ $values[$j] = base64_encode($value);
1764
+ }
1765
+ }
1766
+ }
1767
+ }
1768
+ }
1769
+ }
1770
+
1771
+ /**
1772
+ * Map attribute values from attribute-specific internal format to
1773
+ * ANY type.
1774
+ *
1775
+ * @param array ref $root
1776
+ * @param string $path
1777
+ * @param object $asn1
1778
+ * @access private
1779
+ */
1780
+ function _mapOutAttributes(&$root, $path, $asn1)
1781
+ {
1782
+ $attributes = &$this->_subArray($root, $path);
1783
+
1784
+ if (is_array($attributes)) {
1785
+ $size = count($attributes);
1786
+ for ($i = 0; $i < $size; $i++) {
1787
+ /* [value] contains the DER encoding of an ASN.1 value
1788
+ corresponding to the attribute type identified by type */
1789
+ $id = $attributes[$i]['type'];
1790
+ $map = $this->_getMapping($id);
1791
+ if ($map === false) {
1792
+ user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
1793
+ unset($attributes[$i]);
1794
+ } elseif (is_array($attributes[$i]['value'])) {
1795
+ $values = &$attributes[$i]['value'];
1796
+ for ($j = 0; $j < count($values); $j++) {
1797
+ switch ($id) {
1798
+ case 'pkcs-9-at-extensionRequest':
1799
+ $this->_mapOutExtensions($values, $j, $asn1);
1800
+ break;
1801
+ }
1802
+
1803
+ if (!is_bool($map)) {
1804
+ $temp = $asn1->encodeDER($values[$j], $map);
1805
+ $decoded = $asn1->decodeBER($temp);
1806
+ $values[$j] = $asn1->asn1map($decoded[0], $this->AttributeValue);
1807
+ }
1808
+ }
1809
+ }
1810
+ }
1811
+ }
1812
+ }
1813
+
1814
+ /**
1815
+ * Map DN values from ANY type to DN-specific internal
1816
+ * format.
1817
+ *
1818
+ * @param array ref $root
1819
+ * @param string $path
1820
+ * @param object $asn1
1821
+ * @access private
1822
+ */
1823
+ function _mapInDNs(&$root, $path, $asn1)
1824
+ {
1825
+ $dns = &$this->_subArray($root, $path);
1826
+
1827
+ if (is_array($dns)) {
1828
+ for ($i = 0; $i < count($dns); $i++) {
1829
+ for ($j = 0; $j < count($dns[$i]); $j++) {
1830
+ $type = $dns[$i][$j]['type'];
1831
+ $value = &$dns[$i][$j]['value'];
1832
+ if (is_object($value) && strtolower(get_class($value)) == 'file_asn1_element') {
1833
+ $map = $this->_getMapping($type);
1834
+ if (!is_bool($map)) {
1835
+ $decoded = $asn1->decodeBER($value);
1836
+ $value = $asn1->asn1map($decoded[0], $map);
1837
+ }
1838
+ }
1839
+ }
1840
+ }
1841
+ }
1842
+ }
1843
+
1844
+ /**
1845
+ * Map DN values from DN-specific internal format to
1846
+ * ANY type.
1847
+ *
1848
+ * @param array ref $root
1849
+ * @param string $path
1850
+ * @param object $asn1
1851
+ * @access private
1852
+ */
1853
+ function _mapOutDNs(&$root, $path, $asn1)
1854
+ {
1855
+ $dns = &$this->_subArray($root, $path);
1856
+
1857
+ if (is_array($dns)) {
1858
+ $size = count($dns);
1859
+ for ($i = 0; $i < $size; $i++) {
1860
+ for ($j = 0; $j < count($dns[$i]); $j++) {
1861
+ $type = $dns[$i][$j]['type'];
1862
+ $value = &$dns[$i][$j]['value'];
1863
+ if (is_object($value) && strtolower(get_class($value)) == 'file_asn1_element') {
1864
+ continue;
1865
+ }
1866
+
1867
+ $map = $this->_getMapping($type);
1868
+ if (!is_bool($map)) {
1869
+ $value = new File_ASN1_Element($asn1->encodeDER($value, $map));
1870
+ }
1871
+ }
1872
+ }
1873
+ }
1874
+ }
1875
+
1876
+ /**
1877
+ * Associate an extension ID to an extension mapping
1878
+ *
1879
+ * @param string $extnId
1880
+ * @access private
1881
+ * @return mixed
1882
+ */
1883
+ function _getMapping($extnId)
1884
+ {
1885
+ if (!is_string($extnId)) { // eg. if it's a File_ASN1_Element object
1886
+ return true;
1887
+ }
1888
+
1889
+ switch ($extnId) {
1890
+ case 'id-ce-keyUsage':
1891
+ return $this->KeyUsage;
1892
+ case 'id-ce-basicConstraints':
1893
+ return $this->BasicConstraints;
1894
+ case 'id-ce-subjectKeyIdentifier':
1895
+ return $this->KeyIdentifier;
1896
+ case 'id-ce-cRLDistributionPoints':
1897
+ return $this->CRLDistributionPoints;
1898
+ case 'id-ce-authorityKeyIdentifier':
1899
+ return $this->AuthorityKeyIdentifier;
1900
+ case 'id-ce-certificatePolicies':
1901
+ return $this->CertificatePolicies;
1902
+ case 'id-ce-extKeyUsage':
1903
+ return $this->ExtKeyUsageSyntax;
1904
+ case 'id-pe-authorityInfoAccess':
1905
+ return $this->AuthorityInfoAccessSyntax;
1906
+ case 'id-ce-subjectAltName':
1907
+ return $this->SubjectAltName;
1908
+ case 'id-ce-subjectDirectoryAttributes':
1909
+ return $this->SubjectDirectoryAttributes;
1910
+ case 'id-ce-privateKeyUsagePeriod':
1911
+ return $this->PrivateKeyUsagePeriod;
1912
+ case 'id-ce-issuerAltName':
1913
+ return $this->IssuerAltName;
1914
+ case 'id-ce-policyMappings':
1915
+ return $this->PolicyMappings;
1916
+ case 'id-ce-nameConstraints':
1917
+ return $this->NameConstraints;
1918
+
1919
+ case 'netscape-cert-type':
1920
+ return $this->netscape_cert_type;
1921
+ case 'netscape-comment':
1922
+ return $this->netscape_comment;
1923
+ case 'netscape-ca-policy-url':
1924
+ return $this->netscape_ca_policy_url;
1925
+
1926
+ // since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets
1927
+ // back around to asn1map() and we don't want it decoded again.
1928
+ //case 'id-qt-cps':
1929
+ // return $this->CPSuri;
1930
+ case 'id-qt-unotice':
1931
+ return $this->UserNotice;
1932
+
1933
+ // the following OIDs are unsupported but we don't want them to give notices when calling saveX509().
1934
+ case 'id-pe-logotype': // http://www.ietf.org/rfc/rfc3709.txt
1935
+ case 'entrustVersInfo':
1936
+ // http://support.microsoft.com/kb/287547
1937
+ case '1.3.6.1.4.1.311.20.2': // szOID_ENROLL_CERTTYPE_EXTENSION
1938
+ case '1.3.6.1.4.1.311.21.1': // szOID_CERTSRV_CA_VERSION
1939
+ // "SET Secure Electronic Transaction Specification"
1940
+ // http://www.maithean.com/docs/set_bk3.pdf
1941
+ case '2.23.42.7.0': // id-set-hashedRootKey
1942
+ // "Certificate Transparency"
1943
+ // https://tools.ietf.org/html/rfc6962
1944
+ case '1.3.6.1.4.1.11129.2.4.2':
1945
+ return true;
1946
+
1947
+ // CSR attributes
1948
+ case 'pkcs-9-at-unstructuredName':
1949
+ return $this->PKCS9String;
1950
+ case 'pkcs-9-at-challengePassword':
1951
+ return $this->DirectoryString;
1952
+ case 'pkcs-9-at-extensionRequest':
1953
+ return $this->Extensions;
1954
+
1955
+ // CRL extensions.
1956
+ case 'id-ce-cRLNumber':
1957
+ return $this->CRLNumber;
1958
+ case 'id-ce-deltaCRLIndicator':
1959
+ return $this->CRLNumber;
1960
+ case 'id-ce-issuingDistributionPoint':
1961
+ return $this->IssuingDistributionPoint;
1962
+ case 'id-ce-freshestCRL':
1963
+ return $this->CRLDistributionPoints;
1964
+ case 'id-ce-cRLReasons':
1965
+ return $this->CRLReason;
1966
+ case 'id-ce-invalidityDate':
1967
+ return $this->InvalidityDate;
1968
+ case 'id-ce-certificateIssuer':
1969
+ return $this->CertificateIssuer;
1970
+ case 'id-ce-holdInstructionCode':
1971
+ return $this->HoldInstructionCode;
1972
+ case 'id-at-postalAddress':
1973
+ return $this->PostalAddress;
1974
+ }
1975
+
1976
+ return false;
1977
+ }
1978
+
1979
+ /**
1980
+ * Load an X.509 certificate as a certificate authority
1981
+ *
1982
+ * @param string $cert
1983
+ * @access public
1984
+ * @return bool
1985
+ */
1986
+ function loadCA($cert)
1987
+ {
1988
+ $olddn = $this->dn;
1989
+ $oldcert = $this->currentCert;
1990
+ $oldsigsubj = $this->signatureSubject;
1991
+ $oldkeyid = $this->currentKeyIdentifier;
1992
+
1993
+ $cert = $this->loadX509($cert);
1994
+ if (!$cert) {
1995
+ $this->dn = $olddn;
1996
+ $this->currentCert = $oldcert;
1997
+ $this->signatureSubject = $oldsigsubj;
1998
+ $this->currentKeyIdentifier = $oldkeyid;
1999
+
2000
+ return false;
2001
+ }
2002
+
2003
+ /* From RFC5280 "PKIX Certificate and CRL Profile":
2004
+
2005
+ If the keyUsage extension is present, then the subject public key
2006
+ MUST NOT be used to verify signatures on certificates or CRLs unless
2007
+ the corresponding keyCertSign or cRLSign bit is set. */
2008
+ //$keyUsage = $this->getExtension('id-ce-keyUsage');
2009
+ //if ($keyUsage && !in_array('keyCertSign', $keyUsage)) {
2010
+ // return false;
2011
+ //}
2012
+
2013
+ /* From RFC5280 "PKIX Certificate and CRL Profile":
2014
+
2015
+ The cA boolean indicates whether the certified public key may be used
2016
+ to verify certificate signatures. If the cA boolean is not asserted,
2017
+ then the keyCertSign bit in the key usage extension MUST NOT be
2018
+ asserted. If the basic constraints extension is not present in a
2019
+ version 3 certificate, or the extension is present but the cA boolean
2020
+ is not asserted, then the certified public key MUST NOT be used to
2021
+ verify certificate signatures. */
2022
+ //$basicConstraints = $this->getExtension('id-ce-basicConstraints');
2023
+ //if (!$basicConstraints || !$basicConstraints['cA']) {
2024
+ // return false;
2025
+ //}
2026
+
2027
+ $this->CAs[] = $cert;
2028
+
2029
+ $this->dn = $olddn;
2030
+ $this->currentCert = $oldcert;
2031
+ $this->signatureSubject = $oldsigsubj;
2032
+
2033
+ return true;
2034
+ }
2035
+
2036
+ /**
2037
+ * Validate an X.509 certificate against a URL
2038
+ *
2039
+ * From RFC2818 "HTTP over TLS":
2040
+ *
2041
+ * Matching is performed using the matching rules specified by
2042
+ * [RFC2459]. If more than one identity of a given type is present in
2043
+ * the certificate (e.g., more than one dNSName name, a match in any one
2044
+ * of the set is considered acceptable.) Names may contain the wildcard
2045
+ * character * which is considered to match any single domain name
2046
+ * component or component fragment. E.g., *.a.com matches foo.a.com but
2047
+ * not bar.foo.a.com. f*.com matches foo.com but not bar.com.
2048
+ *
2049
+ * @param string $url
2050
+ * @access public
2051
+ * @return bool
2052
+ */
2053
+ function validateURL($url)
2054
+ {
2055
+ if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
2056
+ return false;
2057
+ }
2058
+
2059
+ $components = parse_url($url);
2060
+ if (!isset($components['host'])) {
2061
+ return false;
2062
+ }
2063
+
2064
+ if ($names = $this->getExtension('id-ce-subjectAltName')) {
2065
+ foreach ($names as $key => $value) {
2066
+ $value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value);
2067
+ switch ($key) {
2068
+ case 'dNSName':
2069
+ /* From RFC2818 "HTTP over TLS":
2070
+
2071
+ If a subjectAltName extension of type dNSName is present, that MUST
2072
+ be used as the identity. Otherwise, the (most specific) Common Name
2073
+ field in the Subject field of the certificate MUST be used. Although
2074
+ the use of the Common Name is existing practice, it is deprecated and
2075
+ Certification Authorities are encouraged to use the dNSName instead. */
2076
+ if (preg_match('#^' . $value . '$#', $components['host'])) {
2077
+ return true;
2078
+ }
2079
+ break;
2080
+ case 'iPAddress':
2081
+ /* From RFC2818 "HTTP over TLS":
2082
+
2083
+ In some cases, the URI is specified as an IP address rather than a
2084
+ hostname. In this case, the iPAddress subjectAltName must be present
2085
+ in the certificate and must exactly match the IP in the URI. */
2086
+ if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
2087
+ return true;
2088
+ }
2089
+ }
2090
+ }
2091
+ return false;
2092
+ }
2093
+
2094
+ if ($value = $this->getDNProp('id-at-commonName')) {
2095
+ $value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value[0]);
2096
+ return preg_match('#^' . $value . '$#', $components['host']);
2097
+ }
2098
+
2099
+ return false;
2100
+ }
2101
+
2102
+ /**
2103
+ * Validate a date
2104
+ *
2105
+ * If $date isn't defined it is assumed to be the current date.
2106
+ *
2107
+ * @param int $date optional
2108
+ * @access public
2109
+ */
2110
+ function validateDate($date = null)
2111
+ {
2112
+ if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
2113
+ return false;
2114
+ }
2115
+
2116
+ if (!isset($date)) {
2117
+ $date = time();
2118
+ }
2119
+
2120
+ $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
2121
+ $notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime'];
2122
+
2123
+ $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter'];
2124
+ $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
2125
+
2126
+ switch (true) {
2127
+ case $date < @strtotime($notBefore):
2128
+ case $date > @strtotime($notAfter):
2129
+ return false;
2130
+ }
2131
+
2132
+ return true;
2133
+ }
2134
+
2135
+ /**
2136
+ * Validate a signature
2137
+ *
2138
+ * Works on X.509 certs, CSR's and CRL's.
2139
+ * Returns true if the signature is verified, false if it is not correct or null on error
2140
+ *
2141
+ * By default returns false for self-signed certs. Call validateSignature(false) to make this support
2142
+ * self-signed.
2143
+ *
2144
+ * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}.
2145
+ *
2146
+ * @param bool $caonly optional
2147
+ * @access public
2148
+ * @return mixed
2149
+ */
2150
+ function validateSignature($caonly = true)
2151
+ {
2152
+ if (!is_array($this->currentCert) || !isset($this->signatureSubject)) {
2153
+ return null;
2154
+ }
2155
+
2156
+ /* TODO:
2157
+ "emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")."
2158
+ -- http://tools.ietf.org/html/rfc5280#section-4.1.2.6
2159
+
2160
+ implement pathLenConstraint in the id-ce-basicConstraints extension */
2161
+
2162
+ switch (true) {
2163
+ case isset($this->currentCert['tbsCertificate']):
2164
+ // self-signed cert
2165
+ switch (true) {
2166
+ case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']:
2167
+ case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(FILE_X509_DN_STRING) === $this->getDN(FILE_X509_DN_STRING):
2168
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
2169
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
2170
+ switch (true) {
2171
+ case !is_array($authorityKey):
2172
+ case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
2173
+ $signingCert = $this->currentCert; // working cert
2174
+ }
2175
+ }
2176
+
2177
+ if (!empty($this->CAs)) {
2178
+ for ($i = 0; $i < count($this->CAs); $i++) {
2179
+ // even if the cert is a self-signed one we still want to see if it's a CA;
2180
+ // if not, we'll conditionally return an error
2181
+ $ca = $this->CAs[$i];
2182
+ switch (true) {
2183
+ case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']:
2184
+ case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(FILE_X509_DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(FILE_X509_DN_STRING, $ca['tbsCertificate']['subject']):
2185
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
2186
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
2187
+ switch (true) {
2188
+ case !is_array($authorityKey):
2189
+ case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
2190
+ $signingCert = $ca; // working cert
2191
+ break 3;
2192
+ }
2193
+ }
2194
+ }
2195
+ if (count($this->CAs) == $i && $caonly) {
2196
+ return false;
2197
+ }
2198
+ } elseif (!isset($signingCert) || $caonly) {
2199
+ return false;
2200
+ }
2201
+ return $this->_validateSignature(
2202
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
2203
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
2204
+ $this->currentCert['signatureAlgorithm']['algorithm'],
2205
+ substr(base64_decode($this->currentCert['signature']), 1),
2206
+ $this->signatureSubject
2207
+ );
2208
+ case isset($this->currentCert['certificationRequestInfo']):
2209
+ return $this->_validateSignature(
2210
+ $this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'],
2211
+ $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'],
2212
+ $this->currentCert['signatureAlgorithm']['algorithm'],
2213
+ substr(base64_decode($this->currentCert['signature']), 1),
2214
+ $this->signatureSubject
2215
+ );
2216
+ case isset($this->currentCert['publicKeyAndChallenge']):
2217
+ return $this->_validateSignature(
2218
+ $this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'],
2219
+ $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'],
2220
+ $this->currentCert['signatureAlgorithm']['algorithm'],
2221
+ substr(base64_decode($this->currentCert['signature']), 1),
2222
+ $this->signatureSubject
2223
+ );
2224
+ case isset($this->currentCert['tbsCertList']):
2225
+ if (!empty($this->CAs)) {
2226
+ for ($i = 0; $i < count($this->CAs); $i++) {
2227
+ $ca = $this->CAs[$i];
2228
+ switch (true) {
2229
+ case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']:
2230
+ case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(FILE_X509_DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(FILE_X509_DN_STRING, $ca['tbsCertificate']['subject']):
2231
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
2232
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
2233
+ switch (true) {
2234
+ case !is_array($authorityKey):
2235
+ case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
2236
+ $signingCert = $ca; // working cert
2237
+ break 3;
2238
+ }
2239
+ }
2240
+ }
2241
+ }
2242
+ if (!isset($signingCert)) {
2243
+ return false;
2244
+ }
2245
+ return $this->_validateSignature(
2246
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
2247
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
2248
+ $this->currentCert['signatureAlgorithm']['algorithm'],
2249
+ substr(base64_decode($this->currentCert['signature']), 1),
2250
+ $this->signatureSubject
2251
+ );
2252
+ default:
2253
+ return false;
2254
+ }
2255
+ }
2256
+
2257
+ /**
2258
+ * Validates a signature
2259
+ *
2260
+ * Returns true if the signature is verified, false if it is not correct or null on error
2261
+ *
2262
+ * @param string $publicKeyAlgorithm
2263
+ * @param string $publicKey
2264
+ * @param string $signatureAlgorithm
2265
+ * @param string $signature
2266
+ * @param string $signatureSubject
2267
+ * @access private
2268
+ * @return int
2269
+ */
2270
+ function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
2271
+ {
2272
+ switch ($publicKeyAlgorithm) {
2273
+ case 'rsaEncryption':
2274
+ if (!class_exists('Crypt_RSA')) {
2275
+ include_once 'Crypt/RSA.php';
2276
+ }
2277
+ $rsa = new Crypt_RSA();
2278
+ $rsa->loadKey($publicKey);
2279
+
2280
+ switch ($signatureAlgorithm) {
2281
+ case 'md2WithRSAEncryption':
2282
+ case 'md5WithRSAEncryption':
2283
+ case 'sha1WithRSAEncryption':
2284
+ case 'sha224WithRSAEncryption':
2285
+ case 'sha256WithRSAEncryption':
2286
+ case 'sha384WithRSAEncryption':
2287
+ case 'sha512WithRSAEncryption':
2288
+ $rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
2289
+ $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
2290
+ if (!@$rsa->verify($signatureSubject, $signature)) {
2291
+ return false;
2292
+ }
2293
+ break;
2294
+ default:
2295
+ return null;
2296
+ }
2297
+ break;
2298
+ default:
2299
+ return null;
2300
+ }
2301
+
2302
+ return true;
2303
+ }
2304
+
2305
+ /**
2306
+ * Reformat public keys
2307
+ *
2308
+ * Reformats a public key to a format supported by phpseclib (if applicable)
2309
+ *
2310
+ * @param string $algorithm
2311
+ * @param string $key
2312
+ * @access private
2313
+ * @return string
2314
+ */
2315
+ function _reformatKey($algorithm, $key)
2316
+ {
2317
+ switch ($algorithm) {
2318
+ case 'rsaEncryption':
2319
+ return
2320
+ "-----BEGIN RSA PUBLIC KEY-----\r\n" .
2321
+ // subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits
2322
+ // in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox
2323
+ // uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do.
2324
+ chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) .
2325
+ '-----END RSA PUBLIC KEY-----';
2326
+ default:
2327
+ return $key;
2328
+ }
2329
+ }
2330
+
2331
+ /**
2332
+ * Decodes an IP address
2333
+ *
2334
+ * Takes in a base64 encoded "blob" and returns a human readable IP address
2335
+ *
2336
+ * @param string $ip
2337
+ * @access private
2338
+ * @return string
2339
+ */
2340
+ function _decodeIP($ip)
2341
+ {
2342
+ $ip = base64_decode($ip);
2343
+ list(, $ip) = unpack('N', $ip);
2344
+ return long2ip($ip);
2345
+ }
2346
+
2347
+ /**
2348
+ * Encodes an IP address
2349
+ *
2350
+ * Takes a human readable IP address into a base64-encoded "blob"
2351
+ *
2352
+ * @param string $ip
2353
+ * @access private
2354
+ * @return string
2355
+ */
2356
+ function _encodeIP($ip)
2357
+ {
2358
+ return base64_encode(pack('N', ip2long($ip)));
2359
+ }
2360
+
2361
+ /**
2362
+ * "Normalizes" a Distinguished Name property
2363
+ *
2364
+ * @param string $propName
2365
+ * @access private
2366
+ * @return mixed
2367
+ */
2368
+ function _translateDNProp($propName)
2369
+ {
2370
+ switch (strtolower($propName)) {
2371
+ case 'id-at-countryname':
2372
+ case 'countryname':
2373
+ case 'c':
2374
+ return 'id-at-countryName';
2375
+ case 'id-at-organizationname':
2376
+ case 'organizationname':
2377
+ case 'o':
2378
+ return 'id-at-organizationName';
2379
+ case 'id-at-dnqualifier':
2380
+ case 'dnqualifier':
2381
+ return 'id-at-dnQualifier';
2382
+ case 'id-at-commonname':
2383
+ case 'commonname':
2384
+ case 'cn':
2385
+ return 'id-at-commonName';
2386
+ case 'id-at-stateorprovincename':
2387
+ case 'stateorprovincename':
2388
+ case 'state':
2389
+ case 'province':
2390
+ case 'provincename':
2391
+ case 'st':
2392
+ return 'id-at-stateOrProvinceName';
2393
+ case 'id-at-localityname':
2394
+ case 'localityname':
2395
+ case 'l':
2396
+ return 'id-at-localityName';
2397
+ case 'id-emailaddress':
2398
+ case 'emailaddress':
2399
+ return 'pkcs-9-at-emailAddress';
2400
+ case 'id-at-serialnumber':
2401
+ case 'serialnumber':
2402
+ return 'id-at-serialNumber';
2403
+ case 'id-at-postalcode':
2404
+ case 'postalcode':
2405
+ return 'id-at-postalCode';
2406
+ case 'id-at-streetaddress':
2407
+ case 'streetaddress':
2408
+ return 'id-at-streetAddress';
2409
+ case 'id-at-name':
2410
+ case 'name':
2411
+ return 'id-at-name';
2412
+ case 'id-at-givenname':
2413
+ case 'givenname':
2414
+ return 'id-at-givenName';
2415
+ case 'id-at-surname':
2416
+ case 'surname':
2417
+ case 'sn':
2418
+ return 'id-at-surname';
2419
+ case 'id-at-initials':
2420
+ case 'initials':
2421
+ return 'id-at-initials';
2422
+ case 'id-at-generationqualifier':
2423
+ case 'generationqualifier':
2424
+ return 'id-at-generationQualifier';
2425
+ case 'id-at-organizationalunitname':
2426
+ case 'organizationalunitname':
2427
+ case 'ou':
2428
+ return 'id-at-organizationalUnitName';
2429
+ case 'id-at-pseudonym':
2430
+ case 'pseudonym':
2431
+ return 'id-at-pseudonym';
2432
+ case 'id-at-title':
2433
+ case 'title':
2434
+ return 'id-at-title';
2435
+ case 'id-at-description':
2436
+ case 'description':
2437
+ return 'id-at-description';
2438
+ case 'id-at-role':
2439
+ case 'role':
2440
+ return 'id-at-role';
2441
+ case 'id-at-uniqueidentifier':
2442
+ case 'uniqueidentifier':
2443
+ case 'x500uniqueidentifier':
2444
+ return 'id-at-uniqueIdentifier';
2445
+ case 'postaladdress':
2446
+ case 'id-at-postaladdress':
2447
+ return 'id-at-postalAddress';
2448
+ default:
2449
+ return false;
2450
+ }
2451
+ }
2452
+
2453
+ /**
2454
+ * Set a Distinguished Name property
2455
+ *
2456
+ * @param string $propName
2457
+ * @param mixed $propValue
2458
+ * @param string $type optional
2459
+ * @access public
2460
+ * @return bool
2461
+ */
2462
+ function setDNProp($propName, $propValue, $type = 'utf8String')
2463
+ {
2464
+ if (empty($this->dn)) {
2465
+ $this->dn = array('rdnSequence' => array());
2466
+ }
2467
+
2468
+ if (($propName = $this->_translateDNProp($propName)) === false) {
2469
+ return false;
2470
+ }
2471
+
2472
+ foreach ((array) $propValue as $v) {
2473
+ if (!is_array($v) && isset($type)) {
2474
+ $v = array($type => $v);
2475
+ }
2476
+ $this->dn['rdnSequence'][] = array(
2477
+ array(
2478
+ 'type' => $propName,
2479
+ 'value'=> $v
2480
+ )
2481
+ );
2482
+ }
2483
+
2484
+ return true;
2485
+ }
2486
+
2487
+ /**
2488
+ * Remove Distinguished Name properties
2489
+ *
2490
+ * @param string $propName
2491
+ * @access public
2492
+ */
2493
+ function removeDNProp($propName)
2494
+ {
2495
+ if (empty($this->dn)) {
2496
+ return;
2497
+ }
2498
+
2499
+ if (($propName = $this->_translateDNProp($propName)) === false) {
2500
+ return;
2501
+ }
2502
+
2503
+ $dn = &$this->dn['rdnSequence'];
2504
+ $size = count($dn);
2505
+ for ($i = 0; $i < $size; $i++) {
2506
+ if ($dn[$i][0]['type'] == $propName) {
2507
+ unset($dn[$i]);
2508
+ }
2509
+ }
2510
+
2511
+ $dn = array_values($dn);
2512
+ }
2513
+
2514
+ /**
2515
+ * Get Distinguished Name properties
2516
+ *
2517
+ * @param string $propName
2518
+ * @param array $dn optional
2519
+ * @param bool $withType optional
2520
+ * @return mixed
2521
+ * @access public
2522
+ */
2523
+ function getDNProp($propName, $dn = null, $withType = false)
2524
+ {
2525
+ if (!isset($dn)) {
2526
+ $dn = $this->dn;
2527
+ }
2528
+
2529
+ if (empty($dn)) {
2530
+ return false;
2531
+ }
2532
+
2533
+ if (($propName = $this->_translateDNProp($propName)) === false) {
2534
+ return false;
2535
+ }
2536
+
2537
+ $asn1 = new File_ASN1();
2538
+ $asn1->loadOIDs($this->oids);
2539
+ $filters = array();
2540
+ $filters['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
2541
+ $asn1->loadFilters($filters);
2542
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
2543
+ $dn = $dn['rdnSequence'];
2544
+ $result = array();
2545
+ for ($i = 0; $i < count($dn); $i++) {
2546
+ if ($dn[$i][0]['type'] == $propName) {
2547
+ $v = $dn[$i][0]['value'];
2548
+ if (!$withType) {
2549
+ if (is_array($v)) {
2550
+ foreach ($v as $type => $s) {
2551
+ $type = array_search($type, $asn1->ANYmap, true);
2552
+ if ($type !== false && isset($asn1->stringTypeSize[$type])) {
2553
+ $s = $asn1->convert($s, $type);
2554
+ if ($s !== false) {
2555
+ $v = $s;
2556
+ break;
2557
+ }
2558
+ }
2559
+ }
2560
+ if (is_array($v)) {
2561
+ $v = array_pop($v); // Always strip data type.
2562
+ }
2563
+ } elseif (is_object($v) && strtolower(get_class($v)) == 'file_asn1_element') {
2564
+ $map = $this->_getMapping($propName);
2565
+ if (!is_bool($map)) {
2566
+ $decoded = $asn1->decodeBER($v);
2567
+ $v = $asn1->asn1map($decoded[0], $map);
2568
+ }
2569
+ }
2570
+ }
2571
+ $result[] = $v;
2572
+ }
2573
+ }
2574
+
2575
+ return $result;
2576
+ }
2577
+
2578
+ /**
2579
+ * Set a Distinguished Name
2580
+ *
2581
+ * @param mixed $dn
2582
+ * @param bool $merge optional
2583
+ * @param string $type optional
2584
+ * @access public
2585
+ * @return bool
2586
+ */
2587
+ function setDN($dn, $merge = false, $type = 'utf8String')
2588
+ {
2589
+ if (!$merge) {
2590
+ $this->dn = null;
2591
+ }
2592
+
2593
+ if (is_array($dn)) {
2594
+ if (isset($dn['rdnSequence'])) {
2595
+ $this->dn = $dn; // No merge here.
2596
+ return true;
2597
+ }
2598
+
2599
+ // handles stuff generated by openssl_x509_parse()
2600
+ foreach ($dn as $prop => $value) {
2601
+ if (!$this->setDNProp($prop, $value, $type)) {
2602
+ return false;
2603
+ }
2604
+ }
2605
+ return true;
2606
+ }
2607
+
2608
+ // handles everything else
2609
+ $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
2610
+ for ($i = 1; $i < count($results); $i+=2) {
2611
+ $prop = trim($results[$i], ', =/');
2612
+ $value = $results[$i + 1];
2613
+ if (!$this->setDNProp($prop, $value, $type)) {
2614
+ return false;
2615
+ }
2616
+ }
2617
+
2618
+ return true;
2619
+ }
2620
+
2621
+ /**
2622
+ * Get the Distinguished Name for a certificates subject
2623
+ *
2624
+ * @param mixed $format optional
2625
+ * @param array $dn optional
2626
+ * @access public
2627
+ * @return bool
2628
+ */
2629
+ function getDN($format = FILE_X509_DN_ARRAY, $dn = null)
2630
+ {
2631
+ if (!isset($dn)) {
2632
+ $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn;
2633
+ }
2634
+
2635
+ switch ((int) $format) {
2636
+ case FILE_X509_DN_ARRAY:
2637
+ return $dn;
2638
+ case FILE_X509_DN_ASN1:
2639
+ $asn1 = new File_ASN1();
2640
+ $asn1->loadOIDs($this->oids);
2641
+ $filters = array();
2642
+ $filters['rdnSequence']['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
2643
+ $asn1->loadFilters($filters);
2644
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
2645
+ return $asn1->encodeDER($dn, $this->Name);
2646
+ case FILE_X509_DN_CANON:
2647
+ // No SEQUENCE around RDNs and all string values normalized as
2648
+ // trimmed lowercase UTF-8 with all spacing as one blank.
2649
+ // constructed RDNs will not be canonicalized
2650
+ $asn1 = new File_ASN1();
2651
+ $asn1->loadOIDs($this->oids);
2652
+ $filters = array();
2653
+ $filters['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
2654
+ $asn1->loadFilters($filters);
2655
+ $result = '';
2656
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
2657
+ foreach ($dn['rdnSequence'] as $rdn) {
2658
+ foreach ($rdn as $i => $attr) {
2659
+ $attr = &$rdn[$i];
2660
+ if (is_array($attr['value'])) {
2661
+ foreach ($attr['value'] as $type => $v) {
2662
+ $type = array_search($type, $asn1->ANYmap, true);
2663
+ if ($type !== false && isset($asn1->stringTypeSize[$type])) {
2664
+ $v = $asn1->convert($v, $type);
2665
+ if ($v !== false) {
2666
+ $v = preg_replace('/\s+/', ' ', $v);
2667
+ $attr['value'] = strtolower(trim($v));
2668
+ break;
2669
+ }
2670
+ }
2671
+ }
2672
+ }
2673
+ }
2674
+ $result .= $asn1->encodeDER($rdn, $this->RelativeDistinguishedName);
2675
+ }
2676
+ return $result;
2677
+ case FILE_X509_DN_HASH:
2678
+ $dn = $this->getDN(FILE_X509_DN_CANON, $dn);
2679
+ if (!class_exists('Crypt_Hash')) {
2680
+ include_once 'Crypt/Hash.php';
2681
+ }
2682
+ $hash = new Crypt_Hash('sha1');
2683
+ $hash = $hash->hash($dn);
2684
+ extract(unpack('Vhash', $hash));
2685
+ return strtolower(bin2hex(pack('N', $hash)));
2686
+ }
2687
+
2688
+ // Default is to return a string.
2689
+ $start = true;
2690
+ $output = '';
2691
+ $result = array();
2692
+ $asn1 = new File_ASN1();
2693
+ $asn1->loadOIDs($this->oids);
2694
+ $filters = array();
2695
+ $filters['rdnSequence']['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
2696
+ $asn1->loadFilters($filters);
2697
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
2698
+ foreach ($dn['rdnSequence'] as $field) {
2699
+ $prop = $field[0]['type'];
2700
+ $value = $field[0]['value'];
2701
+
2702
+ $delim = ', ';
2703
+ switch ($prop) {
2704
+ case 'id-at-countryName':
2705
+ $desc = 'C';
2706
+ break;
2707
+ case 'id-at-stateOrProvinceName':
2708
+ $desc = 'ST';
2709
+ break;
2710
+ case 'id-at-organizationName':
2711
+ $desc = 'O';
2712
+ break;
2713
+ case 'id-at-organizationalUnitName':
2714
+ $desc = 'OU';
2715
+ break;
2716
+ case 'id-at-commonName':
2717
+ $desc = 'CN';
2718
+ break;
2719
+ case 'id-at-localityName':
2720
+ $desc = 'L';
2721
+ break;
2722
+ case 'id-at-surname':
2723
+ $desc = 'SN';
2724
+ break;
2725
+ case 'id-at-uniqueIdentifier':
2726
+ $delim = '/';
2727
+ $desc = 'x500UniqueIdentifier';
2728
+ break;
2729
+ case 'id-at-postalAddress':
2730
+ $delim = '/';
2731
+ $desc = 'postalAddress';
2732
+ break;
2733
+ default:
2734
+ $delim = '/';
2735
+ $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop);
2736
+ }
2737
+
2738
+ if (!$start) {
2739
+ $output.= $delim;
2740
+ }
2741
+ if (is_array($value)) {
2742
+ foreach ($value as $type => $v) {
2743
+ $type = array_search($type, $asn1->ANYmap, true);
2744
+ if ($type !== false && isset($asn1->stringTypeSize[$type])) {
2745
+ $v = $asn1->convert($v, $type);
2746
+ if ($v !== false) {
2747
+ $value = $v;
2748
+ break;
2749
+ }
2750
+ }
2751
+ }
2752
+ if (is_array($value)) {
2753
+ $value = array_pop($value); // Always strip data type.
2754
+ }
2755
+ } elseif (is_object($value) && strtolower(get_class($value)) == 'file_asn1_element') {
2756
+ $callback = create_function('$x', 'return "\x" . bin2hex($x[0]);');
2757
+ $value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element));
2758
+ }
2759
+ $output.= $desc . '=' . $value;
2760
+ $result[$desc] = isset($result[$desc]) ?
2761
+ array_merge((array) $dn[$prop], array($value)) :
2762
+ $value;
2763
+ $start = false;
2764
+ }
2765
+
2766
+ return $format == FILE_X509_DN_OPENSSL ? $result : $output;
2767
+ }
2768
+
2769
+ /**
2770
+ * Get the Distinguished Name for a certificate/crl issuer
2771
+ *
2772
+ * @param int $format optional
2773
+ * @access public
2774
+ * @return mixed
2775
+ */
2776
+ function getIssuerDN($format = FILE_X509_DN_ARRAY)
2777
+ {
2778
+ switch (true) {
2779
+ case !isset($this->currentCert) || !is_array($this->currentCert):
2780
+ break;
2781
+ case isset($this->currentCert['tbsCertificate']):
2782
+ return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']);
2783
+ case isset($this->currentCert['tbsCertList']):
2784
+ return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']);
2785
+ }
2786
+
2787
+ return false;
2788
+ }
2789
+
2790
+ /**
2791
+ * Get the Distinguished Name for a certificate/csr subject
2792
+ * Alias of getDN()
2793
+ *
2794
+ * @param int $format optional
2795
+ * @access public
2796
+ * @return mixed
2797
+ */
2798
+ function getSubjectDN($format = FILE_X509_DN_ARRAY)
2799
+ {
2800
+ switch (true) {
2801
+ case !empty($this->dn):
2802
+ return $this->getDN($format);
2803
+ case !isset($this->currentCert) || !is_array($this->currentCert):
2804
+ break;
2805
+ case isset($this->currentCert['tbsCertificate']):
2806
+ return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']);
2807
+ case isset($this->currentCert['certificationRequestInfo']):
2808
+ return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']);
2809
+ }
2810
+
2811
+ return false;
2812
+ }
2813
+
2814
+ /**
2815
+ * Get an individual Distinguished Name property for a certificate/crl issuer
2816
+ *
2817
+ * @param string $propName
2818
+ * @param bool $withType optional
2819
+ * @access public
2820
+ * @return mixed
2821
+ */
2822
+ function getIssuerDNProp($propName, $withType = false)
2823
+ {
2824
+ switch (true) {
2825
+ case !isset($this->currentCert) || !is_array($this->currentCert):
2826
+ break;
2827
+ case isset($this->currentCert['tbsCertificate']):
2828
+ return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType);
2829
+ case isset($this->currentCert['tbsCertList']):
2830
+ return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType);
2831
+ }
2832
+
2833
+ return false;
2834
+ }
2835
+
2836
+ /**
2837
+ * Get an individual Distinguished Name property for a certificate/csr subject
2838
+ *
2839
+ * @param string $propName
2840
+ * @param bool $withType optional
2841
+ * @access public
2842
+ * @return mixed
2843
+ */
2844
+ function getSubjectDNProp($propName, $withType = false)
2845
+ {
2846
+ switch (true) {
2847
+ case !empty($this->dn):
2848
+ return $this->getDNProp($propName, null, $withType);
2849
+ case !isset($this->currentCert) || !is_array($this->currentCert):
2850
+ break;
2851
+ case isset($this->currentCert['tbsCertificate']):
2852
+ return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType);
2853
+ case isset($this->currentCert['certificationRequestInfo']):
2854
+ return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType);
2855
+ }
2856
+
2857
+ return false;
2858
+ }
2859
+
2860
+ /**
2861
+ * Get the certificate chain for the current cert
2862
+ *
2863
+ * @access public
2864
+ * @return mixed
2865
+ */
2866
+ function getChain()
2867
+ {
2868
+ $chain = array($this->currentCert);
2869
+
2870
+ if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
2871
+ return false;
2872
+ }
2873
+ if (empty($this->CAs)) {
2874
+ return $chain;
2875
+ }
2876
+ while (true) {
2877
+ $currentCert = $chain[count($chain) - 1];
2878
+ for ($i = 0; $i < count($this->CAs); $i++) {
2879
+ $ca = $this->CAs[$i];
2880
+ if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) {
2881
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert);
2882
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
2883
+ switch (true) {
2884
+ case !is_array($authorityKey):
2885
+ case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
2886
+ if ($currentCert === $ca) {
2887
+ break 3;
2888
+ }
2889
+ $chain[] = $ca;
2890
+ break 2;
2891
+ }
2892
+ }
2893
+ }
2894
+ if ($i == count($this->CAs)) {
2895
+ break;
2896
+ }
2897
+ }
2898
+ foreach ($chain as $key => $value) {
2899
+ $chain[$key] = new File_X509();
2900
+ $chain[$key]->loadX509($value);
2901
+ }
2902
+ return $chain;
2903
+ }
2904
+
2905
+ /**
2906
+ * Set public key
2907
+ *
2908
+ * Key needs to be a Crypt_RSA object
2909
+ *
2910
+ * @param object $key
2911
+ * @access public
2912
+ * @return bool
2913
+ */
2914
+ function setPublicKey($key)
2915
+ {
2916
+ $key->setPublicKey();
2917
+ $this->publicKey = $key;
2918
+ }
2919
+
2920
+ /**
2921
+ * Set private key
2922
+ *
2923
+ * Key needs to be a Crypt_RSA object
2924
+ *
2925
+ * @param object $key
2926
+ * @access public
2927
+ */
2928
+ function setPrivateKey($key)
2929
+ {
2930
+ $this->privateKey = $key;
2931
+ }
2932
+
2933
+ /**
2934
+ * Set challenge
2935
+ *
2936
+ * Used for SPKAC CSR's
2937
+ *
2938
+ * @param string $challenge
2939
+ * @access public
2940
+ */
2941
+ function setChallenge($challenge)
2942
+ {
2943
+ $this->challenge = $challenge;
2944
+ }
2945
+
2946
+ /**
2947
+ * Gets the public key
2948
+ *
2949
+ * Returns a Crypt_RSA object or a false.
2950
+ *
2951
+ * @access public
2952
+ * @return mixed
2953
+ */
2954
+ function getPublicKey()
2955
+ {
2956
+ if (isset($this->publicKey)) {
2957
+ return $this->publicKey;
2958
+ }
2959
+
2960
+ if (isset($this->currentCert) && is_array($this->currentCert)) {
2961
+ foreach (array('tbsCertificate/subjectPublicKeyInfo', 'certificationRequestInfo/subjectPKInfo') as $path) {
2962
+ $keyinfo = $this->_subArray($this->currentCert, $path);
2963
+ if (!empty($keyinfo)) {
2964
+ break;
2965
+ }
2966
+ }
2967
+ }
2968
+ if (empty($keyinfo)) {
2969
+ return false;
2970
+ }
2971
+
2972
+ $key = $keyinfo['subjectPublicKey'];
2973
+
2974
+ switch ($keyinfo['algorithm']['algorithm']) {
2975
+ case 'rsaEncryption':
2976
+ if (!class_exists('Crypt_RSA')) {
2977
+ include_once 'Crypt/RSA.php';
2978
+ }
2979
+ $publicKey = new Crypt_RSA();
2980
+ $publicKey->loadKey($key);
2981
+ $publicKey->setPublicKey();
2982
+ break;
2983
+ default:
2984
+ return false;
2985
+ }
2986
+
2987
+ return $publicKey;
2988
+ }
2989
+
2990
+ /**
2991
+ * Load a Certificate Signing Request
2992
+ *
2993
+ * @param string $csr
2994
+ * @access public
2995
+ * @return mixed
2996
+ */
2997
+ function loadCSR($csr, $mode = FILE_X509_FORMAT_AUTO_DETECT)
2998
+ {
2999
+ if (is_array($csr) && isset($csr['certificationRequestInfo'])) {
3000
+ unset($this->currentCert);
3001
+ unset($this->currentKeyIdentifier);
3002
+ unset($this->signatureSubject);
3003
+ $this->dn = $csr['certificationRequestInfo']['subject'];
3004
+ if (!isset($this->dn)) {
3005
+ return false;
3006
+ }
3007
+
3008
+ $this->currentCert = $csr;
3009
+ return $csr;
3010
+ }
3011
+
3012
+ // see http://tools.ietf.org/html/rfc2986
3013
+
3014
+ $asn1 = new File_ASN1();
3015
+
3016
+ if ($mode != FILE_X509_FORMAT_DER) {
3017
+ $newcsr = $this->_extractBER($csr);
3018
+ if ($mode == FILE_X509_FORMAT_PEM && $csr == $newcsr) {
3019
+ return false;
3020
+ }
3021
+ $csr = $newcsr;
3022
+ }
3023
+ $orig = $csr;
3024
+
3025
+ if ($csr === false) {
3026
+ $this->currentCert = false;
3027
+ return false;
3028
+ }
3029
+
3030
+ $asn1->loadOIDs($this->oids);
3031
+ $decoded = $asn1->decodeBER($csr);
3032
+
3033
+ if (empty($decoded)) {
3034
+ $this->currentCert = false;
3035
+ return false;
3036
+ }
3037
+
3038
+ $csr = $asn1->asn1map($decoded[0], $this->CertificationRequest);
3039
+ if (!isset($csr) || $csr === false) {
3040
+ $this->currentCert = false;
3041
+ return false;
3042
+ }
3043
+
3044
+ $this->_mapInAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
3045
+ $this->_mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
3046
+
3047
+ $this->dn = $csr['certificationRequestInfo']['subject'];
3048
+
3049
+ $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
3050
+
3051
+ $algorithm = &$csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'];
3052
+ $key = &$csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'];
3053
+ $key = $this->_reformatKey($algorithm, $key);
3054
+
3055
+ switch ($algorithm) {
3056
+ case 'rsaEncryption':
3057
+ if (!class_exists('Crypt_RSA')) {
3058
+ include_once 'Crypt/RSA.php';
3059
+ }
3060
+ $this->publicKey = new Crypt_RSA();
3061
+ $this->publicKey->loadKey($key);
3062
+ $this->publicKey->setPublicKey();
3063
+ break;
3064
+ default:
3065
+ $this->publicKey = null;
3066
+ }
3067
+
3068
+ $this->currentKeyIdentifier = null;
3069
+ $this->currentCert = $csr;
3070
+
3071
+ return $csr;
3072
+ }
3073
+
3074
+ /**
3075
+ * Save CSR request
3076
+ *
3077
+ * @param array $csr
3078
+ * @param int $format optional
3079
+ * @access public
3080
+ * @return string
3081
+ */
3082
+ function saveCSR($csr, $format = FILE_X509_FORMAT_PEM)
3083
+ {
3084
+ if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) {
3085
+ return false;
3086
+ }
3087
+
3088
+ switch (true) {
3089
+ case !($algorithm = $this->_subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')):
3090
+ case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
3091
+ break;
3092
+ default:
3093
+ switch ($algorithm) {
3094
+ case 'rsaEncryption':
3095
+ $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']
3096
+ = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])));
3097
+ $csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['parameters'] = null;
3098
+ $csr['signatureAlgorithm']['parameters'] = null;
3099
+ $csr['certificationRequestInfo']['signature']['parameters'] = null;
3100
+ }
3101
+ }
3102
+
3103
+ $asn1 = new File_ASN1();
3104
+
3105
+ $asn1->loadOIDs($this->oids);
3106
+
3107
+ $filters = array();
3108
+ $filters['certificationRequestInfo']['subject']['rdnSequence']['value']
3109
+ = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
3110
+
3111
+ $asn1->loadFilters($filters);
3112
+
3113
+ $this->_mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
3114
+ $this->_mapOutAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
3115
+ $csr = $asn1->encodeDER($csr, $this->CertificationRequest);
3116
+
3117
+ switch ($format) {
3118
+ case FILE_X509_FORMAT_DER:
3119
+ return $csr;
3120
+ // case FILE_X509_FORMAT_PEM:
3121
+ default:
3122
+ return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(base64_encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
3123
+ }
3124
+ }
3125
+
3126
+ /**
3127
+ * Load a SPKAC CSR
3128
+ *
3129
+ * SPKAC's are produced by the HTML5 keygen element:
3130
+ *
3131
+ * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
3132
+ *
3133
+ * @param string $csr
3134
+ * @access public
3135
+ * @return mixed
3136
+ */
3137
+ function loadSPKAC($spkac)
3138
+ {
3139
+ if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) {
3140
+ unset($this->currentCert);
3141
+ unset($this->currentKeyIdentifier);
3142
+ unset($this->signatureSubject);
3143
+ $this->currentCert = $spkac;
3144
+ return $spkac;
3145
+ }
3146
+
3147
+ // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
3148
+
3149
+ $asn1 = new File_ASN1();
3150
+
3151
+ // OpenSSL produces SPKAC's that are preceded by the string SPKAC=
3152
+ $temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac);
3153
+ $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
3154
+ if ($temp != false) {
3155
+ $spkac = $temp;
3156
+ }
3157
+ $orig = $spkac;
3158
+
3159
+ if ($spkac === false) {
3160
+ $this->currentCert = false;
3161
+ return false;
3162
+ }
3163
+
3164
+ $asn1->loadOIDs($this->oids);
3165
+ $decoded = $asn1->decodeBER($spkac);
3166
+
3167
+ if (empty($decoded)) {
3168
+ $this->currentCert = false;
3169
+ return false;
3170
+ }
3171
+
3172
+ $spkac = $asn1->asn1map($decoded[0], $this->SignedPublicKeyAndChallenge);
3173
+
3174
+ if (!isset($spkac) || $spkac === false) {
3175
+ $this->currentCert = false;
3176
+ return false;
3177
+ }
3178
+
3179
+ $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
3180
+
3181
+ $algorithm = &$spkac['publicKeyAndChallenge']['spki']['algorithm']['algorithm'];
3182
+ $key = &$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'];
3183
+ $key = $this->_reformatKey($algorithm, $key);
3184
+
3185
+ switch ($algorithm) {
3186
+ case 'rsaEncryption':
3187
+ if (!class_exists('Crypt_RSA')) {
3188
+ include_once 'Crypt/RSA.php';
3189
+ }
3190
+ $this->publicKey = new Crypt_RSA();
3191
+ $this->publicKey->loadKey($key);
3192
+ $this->publicKey->setPublicKey();
3193
+ break;
3194
+ default:
3195
+ $this->publicKey = null;
3196
+ }
3197
+
3198
+ $this->currentKeyIdentifier = null;
3199
+ $this->currentCert = $spkac;
3200
+
3201
+ return $spkac;
3202
+ }
3203
+
3204
+ /**
3205
+ * Save a SPKAC CSR request
3206
+ *
3207
+ * @param array $csr
3208
+ * @param int $format optional
3209
+ * @access public
3210
+ * @return string
3211
+ */
3212
+ function saveSPKAC($spkac, $format = FILE_X509_FORMAT_PEM)
3213
+ {
3214
+ if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) {
3215
+ return false;
3216
+ }
3217
+
3218
+ $algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
3219
+ switch (true) {
3220
+ case !$algorithm:
3221
+ case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']):
3222
+ break;
3223
+ default:
3224
+ switch ($algorithm) {
3225
+ case 'rsaEncryption':
3226
+ $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']
3227
+ = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
3228
+ }
3229
+ }
3230
+
3231
+ $asn1 = new File_ASN1();
3232
+
3233
+ $asn1->loadOIDs($this->oids);
3234
+ $spkac = $asn1->encodeDER($spkac, $this->SignedPublicKeyAndChallenge);
3235
+
3236
+ switch ($format) {
3237
+ case FILE_X509_FORMAT_DER:
3238
+ return $spkac;
3239
+ // case FILE_X509_FORMAT_PEM:
3240
+ default:
3241
+ // OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much
3242
+ // no other SPKAC decoders phpseclib will use that same format
3243
+ return 'SPKAC=' . base64_encode($spkac);
3244
+ }
3245
+ }
3246
+
3247
+ /**
3248
+ * Load a Certificate Revocation List
3249
+ *
3250
+ * @param string $crl
3251
+ * @access public
3252
+ * @return mixed
3253
+ */
3254
+ function loadCRL($crl, $mode = FILE_X509_FORMAT_AUTO_DETECT)
3255
+ {
3256
+ if (is_array($crl) && isset($crl['tbsCertList'])) {
3257
+ $this->currentCert = $crl;
3258
+ unset($this->signatureSubject);
3259
+ return $crl;
3260
+ }
3261
+
3262
+ $asn1 = new File_ASN1();
3263
+
3264
+ if ($mode != FILE_X509_FORMAT_DER) {
3265
+ $newcrl = $this->_extractBER($crl);
3266
+ if ($mode == FILE_X509_FORMAT_PEM && $crl == $newcrl) {
3267
+ return false;
3268
+ }
3269
+ $crl = $newcrl;
3270
+ }
3271
+ $orig = $crl;
3272
+
3273
+ if ($crl === false) {
3274
+ $this->currentCert = false;
3275
+ return false;
3276
+ }
3277
+
3278
+ $asn1->loadOIDs($this->oids);
3279
+ $decoded = $asn1->decodeBER($crl);
3280
+
3281
+ if (empty($decoded)) {
3282
+ $this->currentCert = false;
3283
+ return false;
3284
+ }
3285
+
3286
+ $crl = $asn1->asn1map($decoded[0], $this->CertificateList);
3287
+ if (!isset($crl) || $crl === false) {
3288
+ $this->currentCert = false;
3289
+ return false;
3290
+ }
3291
+
3292
+ $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
3293
+
3294
+ $this->_mapInDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
3295
+ if ($this->_isSubArrayValid($crl, 'tbsCertList/crlExtensions')) {
3296
+ $this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
3297
+ }
3298
+ if ($this->_isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) {
3299
+ $rclist_ref = &$this->_subArrayUnchecked($crl, 'tbsCertList/revokedCertificates');
3300
+ if ($rclist_ref) {
3301
+ $rclist = $crl['tbsCertList']['revokedCertificates'];
3302
+ foreach ($rclist as $i => $extension) {
3303
+ if ($this->_isSubArrayValid($rclist, "$i/crlEntryExtensions", $asn1)) {
3304
+ $this->_mapInExtensions($rclist_ref, "$i/crlEntryExtensions", $asn1);
3305
+ }
3306
+ }
3307
+ }
3308
+ }
3309
+
3310
+ $this->currentKeyIdentifier = null;
3311
+ $this->currentCert = $crl;
3312
+
3313
+ return $crl;
3314
+ }
3315
+
3316
+ /**
3317
+ * Save Certificate Revocation List.
3318
+ *
3319
+ * @param array $crl
3320
+ * @param int $format optional
3321
+ * @access public
3322
+ * @return string
3323
+ */
3324
+ function saveCRL($crl, $format = FILE_X509_FORMAT_PEM)
3325
+ {
3326
+ if (!is_array($crl) || !isset($crl['tbsCertList'])) {
3327
+ return false;
3328
+ }
3329
+
3330
+ $asn1 = new File_ASN1();
3331
+
3332
+ $asn1->loadOIDs($this->oids);
3333
+
3334
+ $filters = array();
3335
+ $filters['tbsCertList']['issuer']['rdnSequence']['value']
3336
+ = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
3337
+ $filters['tbsCertList']['signature']['parameters']
3338
+ = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
3339
+ $filters['signatureAlgorithm']['parameters']
3340
+ = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
3341
+
3342
+ if (empty($crl['tbsCertList']['signature']['parameters'])) {
3343
+ $filters['tbsCertList']['signature']['parameters']
3344
+ = array('type' => FILE_ASN1_TYPE_NULL);
3345
+ }
3346
+
3347
+ if (empty($crl['signatureAlgorithm']['parameters'])) {
3348
+ $filters['signatureAlgorithm']['parameters']
3349
+ = array('type' => FILE_ASN1_TYPE_NULL);
3350
+ }
3351
+
3352
+ $asn1->loadFilters($filters);
3353
+
3354
+ $this->_mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
3355
+ $this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
3356
+ $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates');
3357
+ if (is_array($rclist)) {
3358
+ foreach ($rclist as $i => $extension) {
3359
+ $this->_mapOutExtensions($rclist, "$i/crlEntryExtensions", $asn1);
3360
+ }
3361
+ }
3362
+
3363
+ $crl = $asn1->encodeDER($crl, $this->CertificateList);
3364
+
3365
+ switch ($format) {
3366
+ case FILE_X509_FORMAT_DER:
3367
+ return $crl;
3368
+ // case FILE_X509_FORMAT_PEM:
3369
+ default:
3370
+ return "-----BEGIN X509 CRL-----\r\n" . chunk_split(base64_encode($crl), 64) . '-----END X509 CRL-----';
3371
+ }
3372
+ }
3373
+
3374
+ /**
3375
+ * Helper function to build a time field according to RFC 3280 section
3376
+ * - 4.1.2.5 Validity
3377
+ * - 5.1.2.4 This Update
3378
+ * - 5.1.2.5 Next Update
3379
+ * - 5.1.2.6 Revoked Certificates
3380
+ * by choosing utcTime iff year of date given is before 2050 and generalTime else.
3381
+ *
3382
+ * @param string $date in format date('D, d M Y H:i:s O')
3383
+ * @access private
3384
+ * @return array
3385
+ */
3386
+ function _timeField($date)
3387
+ {
3388
+ $year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
3389
+ if ($year < 2050) {
3390
+ return array('utcTime' => $date);
3391
+ } else {
3392
+ return array('generalTime' => $date);
3393
+ }
3394
+ }
3395
+
3396
+ /**
3397
+ * Sign an X.509 certificate
3398
+ *
3399
+ * $issuer's private key needs to be loaded.
3400
+ * $subject can be either an existing X.509 cert (if you want to resign it),
3401
+ * a CSR or something with the DN and public key explicitly set.
3402
+ *
3403
+ * @param File_X509 $issuer
3404
+ * @param File_X509 $subject
3405
+ * @param string $signatureAlgorithm optional
3406
+ * @access public
3407
+ * @return mixed
3408
+ */
3409
+ function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption')
3410
+ {
3411
+ if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
3412
+ return false;
3413
+ }
3414
+
3415
+ if (isset($subject->publicKey) && !($subjectPublicKey = $subject->_formatSubjectPublicKey())) {
3416
+ return false;
3417
+ }
3418
+
3419
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
3420
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
3421
+
3422
+ if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) {
3423
+ $this->currentCert = $subject->currentCert;
3424
+ $this->currentCert['tbsCertificate']['signature']['algorithm'] = $signatureAlgorithm;
3425
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
3426
+
3427
+ if (!empty($this->startDate)) {
3428
+ $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->_timeField($this->startDate);
3429
+ }
3430
+ if (!empty($this->endDate)) {
3431
+ $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->_timeField($this->endDate);
3432
+ }
3433
+ if (!empty($this->serialNumber)) {
3434
+ $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber;
3435
+ }
3436
+ if (!empty($subject->dn)) {
3437
+ $this->currentCert['tbsCertificate']['subject'] = $subject->dn;
3438
+ }
3439
+ if (!empty($subject->publicKey)) {
3440
+ $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey;
3441
+ }
3442
+ $this->removeExtension('id-ce-authorityKeyIdentifier');
3443
+ if (isset($subject->domains)) {
3444
+ $this->removeExtension('id-ce-subjectAltName');
3445
+ }
3446
+ } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
3447
+ return false;
3448
+ } else {
3449
+ if (!isset($subject->publicKey)) {
3450
+ return false;
3451
+ }
3452
+
3453
+ $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
3454
+ $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year'));
3455
+ if (!empty($this->serialNumber)) {
3456
+ $serialNumber = $this->serialNumber;
3457
+ } else {
3458
+ if (!function_exists('crypt_random_string')) {
3459
+ include_once 'Crypt/Random.php';
3460
+ }
3461
+ /* "The serial number MUST be a positive integer"
3462
+ "Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
3463
+ -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
3464
+
3465
+ for the integer to be positive the leading bit needs to be 0 hence the
3466
+ application of a bitmap
3467
+ */
3468
+ $serialNumber = new Math_BigInteger(crypt_random_string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256);
3469
+ }
3470
+
3471
+ $this->currentCert = array(
3472
+ 'tbsCertificate' =>
3473
+ array(
3474
+ 'version' => 'v3',
3475
+ 'serialNumber' => $serialNumber, // $this->setserialNumber()
3476
+ 'signature' => array('algorithm' => $signatureAlgorithm),
3477
+ 'issuer' => false, // this is going to be overwritten later
3478
+ 'validity' => array(
3479
+ 'notBefore' => $this->_timeField($startDate), // $this->setStartDate()
3480
+ 'notAfter' => $this->_timeField($endDate) // $this->setEndDate()
3481
+ ),
3482
+ 'subject' => $subject->dn,
3483
+ 'subjectPublicKeyInfo' => $subjectPublicKey
3484
+ ),
3485
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
3486
+ 'signature' => false // this is going to be overwritten later
3487
+ );
3488
+
3489
+ // Copy extensions from CSR.
3490
+ $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0);
3491
+
3492
+ if (!empty($csrexts)) {
3493
+ $this->currentCert['tbsCertificate']['extensions'] = $csrexts;
3494
+ }
3495
+ }
3496
+
3497
+ $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn;
3498
+
3499
+ if (isset($issuer->currentKeyIdentifier)) {
3500
+ $this->setExtension('id-ce-authorityKeyIdentifier', array(
3501
+ //'authorityCertIssuer' => array(
3502
+ // array(
3503
+ // 'directoryName' => $issuer->dn
3504
+ // )
3505
+ //),
3506
+ 'keyIdentifier' => $issuer->currentKeyIdentifier
3507
+ ));
3508
+ //$extensions = &$this->currentCert['tbsCertificate']['extensions'];
3509
+ //if (isset($issuer->serialNumber)) {
3510
+ // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
3511
+ //}
3512
+ //unset($extensions);
3513
+ }
3514
+
3515
+ if (isset($subject->currentKeyIdentifier)) {
3516
+ $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier);
3517
+ }
3518
+
3519
+ $altName = array();
3520
+
3521
+ if (isset($subject->domains) && count($subject->domains) > 1) {
3522
+ $altName = array_map(array('File_X509', '_dnsName'), $subject->domains);
3523
+ }
3524
+
3525
+ if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
3526
+ // should an IP address appear as the CN if no domain name is specified? idk
3527
+ //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1);
3528
+ $ipAddresses = array();
3529
+ foreach ($subject->ipAddresses as $ipAddress) {
3530
+ $encoded = $subject->_ipAddress($ipAddress);
3531
+ if ($encoded !== false) {
3532
+ $ipAddresses[] = $encoded;
3533
+ }
3534
+ }
3535
+ if (count($ipAddresses)) {
3536
+ $altName = array_merge($altName, $ipAddresses);
3537
+ }
3538
+ }
3539
+
3540
+ if (!empty($altName)) {
3541
+ $this->setExtension('id-ce-subjectAltName', $altName);
3542
+ }
3543
+
3544
+ if ($this->caFlag) {
3545
+ $keyUsage = $this->getExtension('id-ce-keyUsage');
3546
+ if (!$keyUsage) {
3547
+ $keyUsage = array();
3548
+ }
3549
+
3550
+ $this->setExtension(
3551
+ 'id-ce-keyUsage',
3552
+ array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign'))))
3553
+ );
3554
+
3555
+ $basicConstraints = $this->getExtension('id-ce-basicConstraints');
3556
+ if (!$basicConstraints) {
3557
+ $basicConstraints = array();
3558
+ }
3559
+
3560
+ $this->setExtension(
3561
+ 'id-ce-basicConstraints',
3562
+ array_unique(array_merge(array('cA' => true), $basicConstraints)),
3563
+ true
3564
+ );
3565
+
3566
+ if (!isset($subject->currentKeyIdentifier)) {
3567
+ $this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false);
3568
+ }
3569
+ }
3570
+
3571
+ // resync $this->signatureSubject
3572
+ // save $tbsCertificate in case there are any File_ASN1_Element objects in it
3573
+ $tbsCertificate = $this->currentCert['tbsCertificate'];
3574
+ $this->loadX509($this->saveX509($this->currentCert));
3575
+
3576
+ $result = $this->_sign($issuer->privateKey, $signatureAlgorithm);
3577
+ $result['tbsCertificate'] = $tbsCertificate;
3578
+
3579
+ $this->currentCert = $currentCert;
3580
+ $this->signatureSubject = $signatureSubject;
3581
+
3582
+ return $result;
3583
+ }
3584
+
3585
+ /**
3586
+ * Sign a CSR
3587
+ *
3588
+ * @access public
3589
+ * @return mixed
3590
+ */
3591
+ function signCSR($signatureAlgorithm = 'sha1WithRSAEncryption')
3592
+ {
3593
+ if (!is_object($this->privateKey) || empty($this->dn)) {
3594
+ return false;
3595
+ }
3596
+
3597
+ $origPublicKey = $this->publicKey;
3598
+ $class = get_class($this->privateKey);
3599
+ $this->publicKey = new $class();
3600
+ $this->publicKey->loadKey($this->privateKey->getPublicKey());
3601
+ $this->publicKey->setPublicKey();
3602
+ if (!($publicKey = $this->_formatSubjectPublicKey())) {
3603
+ return false;
3604
+ }
3605
+ $this->publicKey = $origPublicKey;
3606
+
3607
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
3608
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
3609
+
3610
+ if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) {
3611
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
3612
+ if (!empty($this->dn)) {
3613
+ $this->currentCert['certificationRequestInfo']['subject'] = $this->dn;
3614
+ }
3615
+ $this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey;
3616
+ } else {
3617
+ $this->currentCert = array(
3618
+ 'certificationRequestInfo' =>
3619
+ array(
3620
+ 'version' => 'v1',
3621
+ 'subject' => $this->dn,
3622
+ 'subjectPKInfo' => $publicKey
3623
+ ),
3624
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
3625
+ 'signature' => false // this is going to be overwritten later
3626
+ );
3627
+ }
3628
+
3629
+ // resync $this->signatureSubject
3630
+ // save $certificationRequestInfo in case there are any File_ASN1_Element objects in it
3631
+ $certificationRequestInfo = $this->currentCert['certificationRequestInfo'];
3632
+ $this->loadCSR($this->saveCSR($this->currentCert));
3633
+
3634
+ $result = $this->_sign($this->privateKey, $signatureAlgorithm);
3635
+ $result['certificationRequestInfo'] = $certificationRequestInfo;
3636
+
3637
+ $this->currentCert = $currentCert;
3638
+ $this->signatureSubject = $signatureSubject;
3639
+
3640
+ return $result;
3641
+ }
3642
+
3643
+ /**
3644
+ * Sign a SPKAC
3645
+ *
3646
+ * @access public
3647
+ * @return mixed
3648
+ */
3649
+ function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption')
3650
+ {
3651
+ if (!is_object($this->privateKey)) {
3652
+ return false;
3653
+ }
3654
+
3655
+ $origPublicKey = $this->publicKey;
3656
+ $class = get_class($this->privateKey);
3657
+ $this->publicKey = new $class();
3658
+ $this->publicKey->loadKey($this->privateKey->getPublicKey());
3659
+ $this->publicKey->setPublicKey();
3660
+ $publicKey = $this->_formatSubjectPublicKey();
3661
+ if (!$publicKey) {
3662
+ return false;
3663
+ }
3664
+ $this->publicKey = $origPublicKey;
3665
+
3666
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
3667
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
3668
+
3669
+ // re-signing a SPKAC seems silly but since everything else supports re-signing why not?
3670
+ if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) {
3671
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
3672
+ $this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey;
3673
+ if (!empty($this->challenge)) {
3674
+ // the bitwise AND ensures that the output is a valid IA5String
3675
+ $this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("\x7F", strlen($this->challenge));
3676
+ }
3677
+ } else {
3678
+ $this->currentCert = array(
3679
+ 'publicKeyAndChallenge' =>
3680
+ array(
3681
+ 'spki' => $publicKey,
3682
+ // quoting <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen>,
3683
+ // "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
3684
+ // both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
3685
+ // we could alternatively do this instead if we ignored the specs:
3686
+ // crypt_random_string(8) & str_repeat("\x7F", 8)
3687
+ 'challenge' => !empty($this->challenge) ? $this->challenge : ''
3688
+ ),
3689
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
3690
+ 'signature' => false // this is going to be overwritten later
3691
+ );
3692
+ }
3693
+
3694
+ // resync $this->signatureSubject
3695
+ // save $publicKeyAndChallenge in case there are any File_ASN1_Element objects in it
3696
+ $publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge'];
3697
+ $this->loadSPKAC($this->saveSPKAC($this->currentCert));
3698
+
3699
+ $result = $this->_sign($this->privateKey, $signatureAlgorithm);
3700
+ $result['publicKeyAndChallenge'] = $publicKeyAndChallenge;
3701
+
3702
+ $this->currentCert = $currentCert;
3703
+ $this->signatureSubject = $signatureSubject;
3704
+
3705
+ return $result;
3706
+ }
3707
+
3708
+ /**
3709
+ * Sign a CRL
3710
+ *
3711
+ * $issuer's private key needs to be loaded.
3712
+ *
3713
+ * @param File_X509 $issuer
3714
+ * @param File_X509 $crl
3715
+ * @param string $signatureAlgorithm optional
3716
+ * @access public
3717
+ * @return mixed
3718
+ */
3719
+ function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption')
3720
+ {
3721
+ if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
3722
+ return false;
3723
+ }
3724
+
3725
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
3726
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
3727
+ $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
3728
+
3729
+ if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
3730
+ $this->currentCert = $crl->currentCert;
3731
+ $this->currentCert['tbsCertList']['signature']['algorithm'] = $signatureAlgorithm;
3732
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
3733
+ } else {
3734
+ $this->currentCert = array(
3735
+ 'tbsCertList' =>
3736
+ array(
3737
+ 'version' => 'v2',
3738
+ 'signature' => array('algorithm' => $signatureAlgorithm),
3739
+ 'issuer' => false, // this is going to be overwritten later
3740
+ 'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
3741
+ ),
3742
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
3743
+ 'signature' => false // this is going to be overwritten later
3744
+ );
3745
+ }
3746
+
3747
+ $tbsCertList = &$this->currentCert['tbsCertList'];
3748
+ $tbsCertList['issuer'] = $issuer->dn;
3749
+ $tbsCertList['thisUpdate'] = $this->_timeField($thisUpdate);
3750
+
3751
+ if (!empty($this->endDate)) {
3752
+ $tbsCertList['nextUpdate'] = $this->_timeField($this->endDate); // $this->setEndDate()
3753
+ } else {
3754
+ unset($tbsCertList['nextUpdate']);
3755
+ }
3756
+
3757
+ if (!empty($this->serialNumber)) {
3758
+ $crlNumber = $this->serialNumber;
3759
+ } else {
3760
+ $crlNumber = $this->getExtension('id-ce-cRLNumber');
3761
+ // "The CRL number is a non-critical CRL extension that conveys a
3762
+ // monotonically increasing sequence number for a given CRL scope and
3763
+ // CRL issuer. This extension allows users to easily determine when a
3764
+ // particular CRL supersedes another CRL."
3765
+ // -- https://tools.ietf.org/html/rfc5280#section-5.2.3
3766
+ $crlNumber = $crlNumber !== false ? $crlNumber->add(new Math_BigInteger(1)) : null;
3767
+ }
3768
+
3769
+ $this->removeExtension('id-ce-authorityKeyIdentifier');
3770
+ $this->removeExtension('id-ce-issuerAltName');
3771
+
3772
+ // Be sure version >= v2 if some extension found.
3773
+ $version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0;
3774
+ if (!$version) {
3775
+ if (!empty($tbsCertList['crlExtensions'])) {
3776
+ $version = 1; // v2.
3777
+ } elseif (!empty($tbsCertList['revokedCertificates'])) {
3778
+ foreach ($tbsCertList['revokedCertificates'] as $cert) {
3779
+ if (!empty($cert['crlEntryExtensions'])) {
3780
+ $version = 1; // v2.
3781
+ }
3782
+ }
3783
+ }
3784
+
3785
+ if ($version) {
3786
+ $tbsCertList['version'] = $version;
3787
+ }
3788
+ }
3789
+
3790
+ // Store additional extensions.
3791
+ if (!empty($tbsCertList['version'])) { // At least v2.
3792
+ if (!empty($crlNumber)) {
3793
+ $this->setExtension('id-ce-cRLNumber', $crlNumber);
3794
+ }
3795
+
3796
+ if (isset($issuer->currentKeyIdentifier)) {
3797
+ $this->setExtension('id-ce-authorityKeyIdentifier', array(
3798
+ //'authorityCertIssuer' => array(
3799
+ // array(
3800
+ // 'directoryName' => $issuer->dn
3801
+ // )
3802
+ //),
3803
+ 'keyIdentifier' => $issuer->currentKeyIdentifier
3804
+ ));
3805
+ //$extensions = &$tbsCertList['crlExtensions'];
3806
+ //if (isset($issuer->serialNumber)) {
3807
+ // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
3808
+ //}
3809
+ //unset($extensions);
3810
+ }
3811
+
3812
+ $issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert);
3813
+
3814
+ if ($issuerAltName !== false) {
3815
+ $this->setExtension('id-ce-issuerAltName', $issuerAltName);
3816
+ }
3817
+ }
3818
+
3819
+ if (empty($tbsCertList['revokedCertificates'])) {
3820
+ unset($tbsCertList['revokedCertificates']);
3821
+ }
3822
+
3823
+ unset($tbsCertList);
3824
+
3825
+ // resync $this->signatureSubject
3826
+ // save $tbsCertList in case there are any File_ASN1_Element objects in it
3827
+ $tbsCertList = $this->currentCert['tbsCertList'];
3828
+ $this->loadCRL($this->saveCRL($this->currentCert));
3829
+
3830
+ $result = $this->_sign($issuer->privateKey, $signatureAlgorithm);
3831
+ $result['tbsCertList'] = $tbsCertList;
3832
+
3833
+ $this->currentCert = $currentCert;
3834
+ $this->signatureSubject = $signatureSubject;
3835
+
3836
+ return $result;
3837
+ }
3838
+
3839
+ /**
3840
+ * X.509 certificate signing helper function.
3841
+ *
3842
+ * @param object $key
3843
+ * @param File_X509 $subject
3844
+ * @param string $signatureAlgorithm
3845
+ * @access public
3846
+ * @return mixed
3847
+ */
3848
+ function _sign($key, $signatureAlgorithm)
3849
+ {
3850
+ switch (strtolower(get_class($key))) {
3851
+ case 'crypt_rsa':
3852
+ switch ($signatureAlgorithm) {
3853
+ case 'md2WithRSAEncryption':
3854
+ case 'md5WithRSAEncryption':
3855
+ case 'sha1WithRSAEncryption':
3856
+ case 'sha224WithRSAEncryption':
3857
+ case 'sha256WithRSAEncryption':
3858
+ case 'sha384WithRSAEncryption':
3859
+ case 'sha512WithRSAEncryption':
3860
+ $key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
3861
+ $key->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
3862
+
3863
+ $this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject));
3864
+ return $this->currentCert;
3865
+ }
3866
+ default:
3867
+ return false;
3868
+ }
3869
+ }
3870
+
3871
+ /**
3872
+ * Set certificate start date
3873
+ *
3874
+ * @param string $date
3875
+ * @access public
3876
+ */
3877
+ function setStartDate($date)
3878
+ {
3879
+ $this->startDate = @date('D, d M Y H:i:s O', @strtotime($date));
3880
+ }
3881
+
3882
+ /**
3883
+ * Set certificate end date
3884
+ *
3885
+ * @param string $date
3886
+ * @access public
3887
+ */
3888
+ function setEndDate($date)
3889
+ {
3890
+ /*
3891
+ To indicate that a certificate has no well-defined expiration date,
3892
+ the notAfter SHOULD be assigned the GeneralizedTime value of
3893
+ 99991231235959Z.
3894
+
3895
+ -- http://tools.ietf.org/html/rfc5280#section-4.1.2.5
3896
+ */
3897
+ if (strtolower($date) == 'lifetime') {
3898
+ $temp = '99991231235959Z';
3899
+ $asn1 = new File_ASN1();
3900
+ $temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
3901
+ $this->endDate = new File_ASN1_Element($temp);
3902
+ } else {
3903
+ $this->endDate = @date('D, d M Y H:i:s O', @strtotime($date));
3904
+ }
3905
+ }
3906
+
3907
+ /**
3908
+ * Set Serial Number
3909
+ *
3910
+ * @param string $serial
3911
+ * @param $base optional
3912
+ * @access public
3913
+ */
3914
+ function setSerialNumber($serial, $base = -256)
3915
+ {
3916
+ $this->serialNumber = new Math_BigInteger($serial, $base);
3917
+ }
3918
+
3919
+ /**
3920
+ * Turns the certificate into a certificate authority
3921
+ *
3922
+ * @access public
3923
+ */
3924
+ function makeCA()
3925
+ {
3926
+ $this->caFlag = true;
3927
+ }
3928
+
3929
+ /**
3930
+ * Check for validity of subarray
3931
+ *
3932
+ * This is intended for use in conjunction with _subArrayUnchecked(),
3933
+ * implementing the checks included in _subArray() but without copying
3934
+ * a potentially large array by passing its reference by-value to is_array().
3935
+ *
3936
+ * @param array $root
3937
+ * @param string $path
3938
+ * @return boolean
3939
+ * @access private
3940
+ */
3941
+ function _isSubArrayValid($root, $path)
3942
+ {
3943
+ if (!is_array($root)) {
3944
+ return false;
3945
+ }
3946
+
3947
+ foreach (explode('/', $path) as $i) {
3948
+ if (!is_array($root)) {
3949
+ return false;
3950
+ }
3951
+
3952
+ if (!isset($root[$i])) {
3953
+ return true;
3954
+ }
3955
+
3956
+ $root = $root[$i];
3957
+ }
3958
+
3959
+ return true;
3960
+ }
3961
+
3962
+ /**
3963
+ * Get a reference to a subarray
3964
+ *
3965
+ * This variant of _subArray() does no is_array() checking,
3966
+ * so $root should be checked with _isSubArrayValid() first.
3967
+ *
3968
+ * This is here for performance reasons:
3969
+ * Passing a reference (i.e. $root) by-value (i.e. to is_array())
3970
+ * creates a copy. If $root is an especially large array, this is expensive.
3971
+ *
3972
+ * @param array $root
3973
+ * @param string $path absolute path with / as component separator
3974
+ * @param bool $create optional
3975
+ * @access private
3976
+ * @return array|false
3977
+ */
3978
+ function &_subArrayUnchecked(&$root, $path, $create = false)
3979
+ {
3980
+ $false = false;
3981
+
3982
+ foreach (explode('/', $path) as $i) {
3983
+ if (!isset($root[$i])) {
3984
+ if (!$create) {
3985
+ return $false;
3986
+ }
3987
+
3988
+ $root[$i] = array();
3989
+ }
3990
+
3991
+ $root = &$root[$i];
3992
+ }
3993
+
3994
+ return $root;
3995
+ }
3996
+
3997
+ /**
3998
+ * Get a reference to a subarray
3999
+ *
4000
+ * @param array $root
4001
+ * @param string $path absolute path with / as component separator
4002
+ * @param bool $create optional
4003
+ * @access private
4004
+ * @return array|false
4005
+ */
4006
+ function &_subArray(&$root, $path, $create = false)
4007
+ {
4008
+ $false = false;
4009
+
4010
+ if (!is_array($root)) {
4011
+ return $false;
4012
+ }
4013
+
4014
+ foreach (explode('/', $path) as $i) {
4015
+ if (!is_array($root)) {
4016
+ return $false;
4017
+ }
4018
+
4019
+ if (!isset($root[$i])) {
4020
+ if (!$create) {
4021
+ return $false;
4022
+ }
4023
+
4024
+ $root[$i] = array();
4025
+ }
4026
+
4027
+ $root = &$root[$i];
4028
+ }
4029
+
4030
+ return $root;
4031
+ }
4032
+
4033
+ /**
4034
+ * Get a reference to an extension subarray
4035
+ *
4036
+ * @param array $root
4037
+ * @param string $path optional absolute path with / as component separator
4038
+ * @param bool $create optional
4039
+ * @access private
4040
+ * @return array|false
4041
+ */
4042
+ function &_extensions(&$root, $path = null, $create = false)
4043
+ {
4044
+ if (!isset($root)) {
4045
+ $root = $this->currentCert;
4046
+ }
4047
+
4048
+ switch (true) {
4049
+ case !empty($path):
4050
+ case !is_array($root):
4051
+ break;
4052
+ case isset($root['tbsCertificate']):
4053
+ $path = 'tbsCertificate/extensions';
4054
+ break;
4055
+ case isset($root['tbsCertList']):
4056
+ $path = 'tbsCertList/crlExtensions';
4057
+ break;
4058
+ case isset($root['certificationRequestInfo']):
4059
+ $pth = 'certificationRequestInfo/attributes';
4060
+ $attributes = &$this->_subArray($root, $pth, $create);
4061
+
4062
+ if (is_array($attributes)) {
4063
+ foreach ($attributes as $key => $value) {
4064
+ if ($value['type'] == 'pkcs-9-at-extensionRequest') {
4065
+ $path = "$pth/$key/value/0";
4066
+ break 2;
4067
+ }
4068
+ }
4069
+ if ($create) {
4070
+ $key = count($attributes);
4071
+ $attributes[] = array('type' => 'pkcs-9-at-extensionRequest', 'value' => array());
4072
+ $path = "$pth/$key/value/0";
4073
+ }
4074
+ }
4075
+ break;
4076
+ }
4077
+
4078
+ $extensions = &$this->_subArray($root, $path, $create);
4079
+
4080
+ if (!is_array($extensions)) {
4081
+ $false = false;
4082
+ return $false;
4083
+ }
4084
+
4085
+ return $extensions;
4086
+ }
4087
+
4088
+ /**
4089
+ * Remove an Extension
4090
+ *
4091
+ * @param string $id
4092
+ * @param string $path optional
4093
+ * @access private
4094
+ * @return bool
4095
+ */
4096
+ function _removeExtension($id, $path = null)
4097
+ {
4098
+ $extensions = &$this->_extensions($this->currentCert, $path);
4099
+
4100
+ if (!is_array($extensions)) {
4101
+ return false;
4102
+ }
4103
+
4104
+ $result = false;
4105
+ foreach ($extensions as $key => $value) {
4106
+ if ($value['extnId'] == $id) {
4107
+ unset($extensions[$key]);
4108
+ $result = true;
4109
+ }
4110
+ }
4111
+
4112
+ $extensions = array_values($extensions);
4113
+ return $result;
4114
+ }
4115
+
4116
+ /**
4117
+ * Get an Extension
4118
+ *
4119
+ * Returns the extension if it exists and false if not
4120
+ *
4121
+ * @param string $id
4122
+ * @param array $cert optional
4123
+ * @param string $path optional
4124
+ * @access private
4125
+ * @return mixed
4126
+ */
4127
+ function _getExtension($id, $cert = null, $path = null)
4128
+ {
4129
+ $extensions = $this->_extensions($cert, $path);
4130
+
4131
+ if (!is_array($extensions)) {
4132
+ return false;
4133
+ }
4134
+
4135
+ foreach ($extensions as $key => $value) {
4136
+ if ($value['extnId'] == $id) {
4137
+ return $value['extnValue'];
4138
+ }
4139
+ }
4140
+
4141
+ return false;
4142
+ }
4143
+
4144
+ /**
4145
+ * Returns a list of all extensions in use
4146
+ *
4147
+ * @param array $cert optional
4148
+ * @param string $path optional
4149
+ * @access private
4150
+ * @return array
4151
+ */
4152
+ function _getExtensions($cert = null, $path = null)
4153
+ {
4154
+ $exts = $this->_extensions($cert, $path);
4155
+ $extensions = array();
4156
+
4157
+ if (is_array($exts)) {
4158
+ foreach ($exts as $extension) {
4159
+ $extensions[] = $extension['extnId'];
4160
+ }
4161
+ }
4162
+
4163
+ return $extensions;
4164
+ }
4165
+
4166
+ /**
4167
+ * Set an Extension
4168
+ *
4169
+ * @param string $id
4170
+ * @param mixed $value
4171
+ * @param bool $critical optional
4172
+ * @param bool $replace optional
4173
+ * @param string $path optional
4174
+ * @access private
4175
+ * @return bool
4176
+ */
4177
+ function _setExtension($id, $value, $critical = false, $replace = true, $path = null)
4178
+ {
4179
+ $extensions = &$this->_extensions($this->currentCert, $path, true);
4180
+
4181
+ if (!is_array($extensions)) {
4182
+ return false;
4183
+ }
4184
+
4185
+ $newext = array('extnId' => $id, 'critical' => $critical, 'extnValue' => $value);
4186
+
4187
+ foreach ($extensions as $key => $value) {
4188
+ if ($value['extnId'] == $id) {
4189
+ if (!$replace) {
4190
+ return false;
4191
+ }
4192
+
4193
+ $extensions[$key] = $newext;
4194
+ return true;
4195
+ }
4196
+ }
4197
+
4198
+ $extensions[] = $newext;
4199
+ return true;
4200
+ }
4201
+
4202
+ /**
4203
+ * Remove a certificate, CSR or CRL Extension
4204
+ *
4205
+ * @param string $id
4206
+ * @access public
4207
+ * @return bool
4208
+ */
4209
+ function removeExtension($id)
4210
+ {
4211
+ return $this->_removeExtension($id);
4212
+ }
4213
+
4214
+ /**
4215
+ * Get a certificate, CSR or CRL Extension
4216
+ *
4217
+ * Returns the extension if it exists and false if not
4218
+ *
4219
+ * @param string $id
4220
+ * @param array $cert optional
4221
+ * @access public
4222
+ * @return mixed
4223
+ */
4224
+ function getExtension($id, $cert = null)
4225
+ {
4226
+ return $this->_getExtension($id, $cert);
4227
+ }
4228
+
4229
+ /**
4230
+ * Returns a list of all extensions in use in certificate, CSR or CRL
4231
+ *
4232
+ * @param array $cert optional
4233
+ * @access public
4234
+ * @return array
4235
+ */
4236
+ function getExtensions($cert = null)
4237
+ {
4238
+ return $this->_getExtensions($cert);
4239
+ }
4240
+
4241
+ /**
4242
+ * Set a certificate, CSR or CRL Extension
4243
+ *
4244
+ * @param string $id
4245
+ * @param mixed $value
4246
+ * @param bool $critical optional
4247
+ * @param bool $replace optional
4248
+ * @access public
4249
+ * @return bool
4250
+ */
4251
+ function setExtension($id, $value, $critical = false, $replace = true)
4252
+ {
4253
+ return $this->_setExtension($id, $value, $critical, $replace);
4254
+ }
4255
+
4256
+ /**
4257
+ * Remove a CSR attribute.
4258
+ *
4259
+ * @param string $id
4260
+ * @param int $disposition optional
4261
+ * @access public
4262
+ * @return bool
4263
+ */
4264
+ function removeAttribute($id, $disposition = FILE_X509_ATTR_ALL)
4265
+ {
4266
+ $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes');
4267
+
4268
+ if (!is_array($attributes)) {
4269
+ return false;
4270
+ }
4271
+
4272
+ $result = false;
4273
+ foreach ($attributes as $key => $attribute) {
4274
+ if ($attribute['type'] == $id) {
4275
+ $n = count($attribute['value']);
4276
+ switch (true) {
4277
+ case $disposition == FILE_X509_ATTR_APPEND:
4278
+ case $disposition == FILE_X509_ATTR_REPLACE:
4279
+ return false;
4280
+ case $disposition >= $n:
4281
+ $disposition -= $n;
4282
+ break;
4283
+ case $disposition == FILE_X509_ATTR_ALL:
4284
+ case $n == 1:
4285
+ unset($attributes[$key]);
4286
+ $result = true;
4287
+ break;
4288
+ default:
4289
+ unset($attributes[$key]['value'][$disposition]);
4290
+ $attributes[$key]['value'] = array_values($attributes[$key]['value']);
4291
+ $result = true;
4292
+ break;
4293
+ }
4294
+ if ($result && $disposition != FILE_X509_ATTR_ALL) {
4295
+ break;
4296
+ }
4297
+ }
4298
+ }
4299
+
4300
+ $attributes = array_values($attributes);
4301
+ return $result;
4302
+ }
4303
+
4304
+ /**
4305
+ * Get a CSR attribute
4306
+ *
4307
+ * Returns the attribute if it exists and false if not
4308
+ *
4309
+ * @param string $id
4310
+ * @param int $disposition optional
4311
+ * @param array $csr optional
4312
+ * @access public
4313
+ * @return mixed
4314
+ */
4315
+ function getAttribute($id, $disposition = FILE_X509_ATTR_ALL, $csr = null)
4316
+ {
4317
+ if (empty($csr)) {
4318
+ $csr = $this->currentCert;
4319
+ }
4320
+
4321
+ $attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes');
4322
+
4323
+ if (!is_array($attributes)) {
4324
+ return false;
4325
+ }
4326
+
4327
+ foreach ($attributes as $key => $attribute) {
4328
+ if ($attribute['type'] == $id) {
4329
+ $n = count($attribute['value']);
4330
+ switch (true) {
4331
+ case $disposition == FILE_X509_ATTR_APPEND:
4332
+ case $disposition == FILE_X509_ATTR_REPLACE:
4333
+ return false;
4334
+ case $disposition == FILE_X509_ATTR_ALL:
4335
+ return $attribute['value'];
4336
+ case $disposition >= $n:
4337
+ $disposition -= $n;
4338
+ break;
4339
+ default:
4340
+ return $attribute['value'][$disposition];
4341
+ }
4342
+ }
4343
+ }
4344
+
4345
+ return false;
4346
+ }
4347
+
4348
+ /**
4349
+ * Returns a list of all CSR attributes in use
4350
+ *
4351
+ * @param array $csr optional
4352
+ * @access public
4353
+ * @return array
4354
+ */
4355
+ function getAttributes($csr = null)
4356
+ {
4357
+ if (empty($csr)) {
4358
+ $csr = $this->currentCert;
4359
+ }
4360
+
4361
+ $attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes');
4362
+ $attrs = array();
4363
+
4364
+ if (is_array($attributes)) {
4365
+ foreach ($attributes as $attribute) {
4366
+ $attrs[] = $attribute['type'];
4367
+ }
4368
+ }
4369
+
4370
+ return $attrs;
4371
+ }
4372
+
4373
+ /**
4374
+ * Set a CSR attribute
4375
+ *
4376
+ * @param string $id
4377
+ * @param mixed $value
4378
+ * @param bool $disposition optional
4379
+ * @access public
4380
+ * @return bool
4381
+ */
4382
+ function setAttribute($id, $value, $disposition = FILE_X509_ATTR_ALL)
4383
+ {
4384
+ $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes', true);
4385
+
4386
+ if (!is_array($attributes)) {
4387
+ return false;
4388
+ }
4389
+
4390
+ switch ($disposition) {
4391
+ case FILE_X509_ATTR_REPLACE:
4392
+ $disposition = FILE_X509_ATTR_APPEND;
4393
+ case FILE_X509_ATTR_ALL:
4394
+ $this->removeAttribute($id);
4395
+ break;
4396
+ }
4397
+
4398
+ foreach ($attributes as $key => $attribute) {
4399
+ if ($attribute['type'] == $id) {
4400
+ $n = count($attribute['value']);
4401
+ switch (true) {
4402
+ case $disposition == FILE_X509_ATTR_APPEND:
4403
+ $last = $key;
4404
+ break;
4405
+ case $disposition >= $n:
4406
+ $disposition -= $n;
4407
+ break;
4408
+ default:
4409
+ $attributes[$key]['value'][$disposition] = $value;
4410
+ return true;
4411
+ }
4412
+ }
4413
+ }
4414
+
4415
+ switch (true) {
4416
+ case $disposition >= 0:
4417
+ return false;
4418
+ case isset($last):
4419
+ $attributes[$last]['value'][] = $value;
4420
+ break;
4421
+ default:
4422
+ $attributes[] = array('type' => $id, 'value' => $disposition == FILE_X509_ATTR_ALL ? $value: array($value));
4423
+ break;
4424
+ }
4425
+
4426
+ return true;
4427
+ }
4428
+
4429
+ /**
4430
+ * Sets the subject key identifier
4431
+ *
4432
+ * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions.
4433
+ *
4434
+ * @param string $value
4435
+ * @access public
4436
+ */
4437
+ function setKeyIdentifier($value)
4438
+ {
4439
+ if (empty($value)) {
4440
+ unset($this->currentKeyIdentifier);
4441
+ } else {
4442
+ $this->currentKeyIdentifier = base64_encode($value);
4443
+ }
4444
+ }
4445
+
4446
+ /**
4447
+ * Compute a public key identifier.
4448
+ *
4449
+ * Although key identifiers may be set to any unique value, this function
4450
+ * computes key identifiers from public key according to the two
4451
+ * recommended methods (4.2.1.2 RFC 3280).
4452
+ * Highly polymorphic: try to accept all possible forms of key:
4453
+ * - Key object
4454
+ * - File_X509 object with public or private key defined
4455
+ * - Certificate or CSR array
4456
+ * - File_ASN1_Element object
4457
+ * - PEM or DER string
4458
+ *
4459
+ * @param mixed $key optional
4460
+ * @param int $method optional
4461
+ * @access public
4462
+ * @return string binary key identifier
4463
+ */
4464
+ function computeKeyIdentifier($key = null, $method = 1)
4465
+ {
4466
+ if (is_null($key)) {
4467
+ $key = $this;
4468
+ }
4469
+
4470
+ switch (true) {
4471
+ case is_string($key):
4472
+ break;
4473
+ case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
4474
+ return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method);
4475
+ case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
4476
+ return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method);
4477
+ case !is_object($key):
4478
+ return false;
4479
+ case strtolower(get_class($key)) == 'file_asn1_element':
4480
+ // Assume the element is a bitstring-packed key.
4481
+ $asn1 = new File_ASN1();
4482
+ $decoded = $asn1->decodeBER($key->element);
4483
+ if (empty($decoded)) {
4484
+ return false;
4485
+ }
4486
+ $raw = $asn1->asn1map($decoded[0], array('type' => FILE_ASN1_TYPE_BIT_STRING));
4487
+ if (empty($raw)) {
4488
+ return false;
4489
+ }
4490
+ $raw = base64_decode($raw);
4491
+ // If the key is private, compute identifier from its corresponding public key.
4492
+ if (!class_exists('Crypt_RSA')) {
4493
+ include_once 'Crypt/RSA.php';
4494
+ }
4495
+ $key = new Crypt_RSA();
4496
+ if (!$key->loadKey($raw)) {
4497
+ return false; // Not an unencrypted RSA key.
4498
+ }
4499
+ if ($key->getPrivateKey() !== false) { // If private.
4500
+ return $this->computeKeyIdentifier($key, $method);
4501
+ }
4502
+ $key = $raw; // Is a public key.
4503
+ break;
4504
+ case strtolower(get_class($key)) == 'file_x509':
4505
+ if (isset($key->publicKey)) {
4506
+ return $this->computeKeyIdentifier($key->publicKey, $method);
4507
+ }
4508
+ if (isset($key->privateKey)) {
4509
+ return $this->computeKeyIdentifier($key->privateKey, $method);
4510
+ }
4511
+ if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) {
4512
+ return $this->computeKeyIdentifier($key->currentCert, $method);
4513
+ }
4514
+ return false;
4515
+ default: // Should be a key object (i.e.: Crypt_RSA).
4516
+ $key = $key->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
4517
+ break;
4518
+ }
4519
+
4520
+ // If in PEM format, convert to binary.
4521
+ $key = $this->_extractBER($key);
4522
+
4523
+ // Now we have the key string: compute its sha-1 sum.
4524
+ if (!class_exists('Crypt_Hash')) {
4525
+ include_once 'Crypt/Hash.php';
4526
+ }
4527
+ $hash = new Crypt_Hash('sha1');
4528
+ $hash = $hash->hash($key);
4529
+
4530
+ if ($method == 2) {
4531
+ $hash = substr($hash, -8);
4532
+ $hash[0] = chr((ord($hash[0]) & 0x0F) | 0x40);
4533
+ }
4534
+
4535
+ return $hash;
4536
+ }
4537
+
4538
+ /**
4539
+ * Format a public key as appropriate
4540
+ *
4541
+ * @access private
4542
+ * @return array
4543
+ */
4544
+ function _formatSubjectPublicKey()
4545
+ {
4546
+ if (!isset($this->publicKey) || !is_object($this->publicKey)) {
4547
+ return false;
4548
+ }
4549
+
4550
+ switch (strtolower(get_class($this->publicKey))) {
4551
+ case 'crypt_rsa':
4552
+ // the following two return statements do the same thing. i dunno.. i just prefer the later for some reason.
4553
+ // the former is a good example of how to do fuzzing on the public key
4554
+ //return new File_ASN1_Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
4555
+ return array(
4556
+ 'algorithm' => array('algorithm' => 'rsaEncryption'),
4557
+ 'subjectPublicKey' => $this->publicKey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
4558
+ );
4559
+ default:
4560
+ return false;
4561
+ }
4562
+ }
4563
+
4564
+ /**
4565
+ * Set the domain name's which the cert is to be valid for
4566
+ *
4567
+ * @access public
4568
+ * @return array
4569
+ */
4570
+ function setDomain()
4571
+ {
4572
+ $this->domains = func_get_args();
4573
+ $this->removeDNProp('id-at-commonName');
4574
+ $this->setDNProp('id-at-commonName', $this->domains[0]);
4575
+ }
4576
+
4577
+ /**
4578
+ * Set the IP Addresses's which the cert is to be valid for
4579
+ *
4580
+ * @access public
4581
+ * @param string $ipAddress optional
4582
+ */
4583
+ function setIPAddress()
4584
+ {
4585
+ $this->ipAddresses = func_get_args();
4586
+ /*
4587
+ if (!isset($this->domains)) {
4588
+ $this->removeDNProp('id-at-commonName');
4589
+ $this->setDNProp('id-at-commonName', $this->ipAddresses[0]);
4590
+ }
4591
+ */
4592
+ }
4593
+
4594
+ /**
4595
+ * Helper function to build domain array
4596
+ *
4597
+ * @access private
4598
+ * @param string $domain
4599
+ * @return array
4600
+ */
4601
+ function _dnsName($domain)
4602
+ {
4603
+ return array('dNSName' => $domain);
4604
+ }
4605
+
4606
+ /**
4607
+ * Helper function to build IP Address array
4608
+ *
4609
+ * (IPv6 is not currently supported)
4610
+ *
4611
+ * @access private
4612
+ * @param string $address
4613
+ * @return array
4614
+ */
4615
+ function _iPAddress($address)
4616
+ {
4617
+ return array('iPAddress' => $address);
4618
+ }
4619
+
4620
+ /**
4621
+ * Get the index of a revoked certificate.
4622
+ *
4623
+ * @param array $rclist
4624
+ * @param string $serial
4625
+ * @param bool $create optional
4626
+ * @access private
4627
+ * @return int|false
4628
+ */
4629
+ function _revokedCertificate(&$rclist, $serial, $create = false)
4630
+ {
4631
+ $serial = new Math_BigInteger($serial);
4632
+
4633
+ foreach ($rclist as $i => $rc) {
4634
+ if (!($serial->compare($rc['userCertificate']))) {
4635
+ return $i;
4636
+ }
4637
+ }
4638
+
4639
+ if (!$create) {
4640
+ return false;
4641
+ }
4642
+
4643
+ $i = count($rclist);
4644
+ $rclist[] = array('userCertificate' => $serial,
4645
+ 'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O')));
4646
+ return $i;
4647
+ }
4648
+
4649
+ /**
4650
+ * Revoke a certificate.
4651
+ *
4652
+ * @param string $serial
4653
+ * @param string $date optional
4654
+ * @access public
4655
+ * @return bool
4656
+ */
4657
+ function revoke($serial, $date = null)
4658
+ {
4659
+ if (isset($this->currentCert['tbsCertList'])) {
4660
+ if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
4661
+ if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked
4662
+ if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
4663
+ if (!empty($date)) {
4664
+ $rclist[$i]['revocationDate'] = $this->_timeField($date);
4665
+ }
4666
+
4667
+ return true;
4668
+ }
4669
+ }
4670
+ }
4671
+ }
4672
+
4673
+ return false;
4674
+ }
4675
+
4676
+ /**
4677
+ * Unrevoke a certificate.
4678
+ *
4679
+ * @param string $serial
4680
+ * @access public
4681
+ * @return bool
4682
+ */
4683
+ function unrevoke($serial)
4684
+ {
4685
+ if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
4686
+ if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
4687
+ unset($rclist[$i]);
4688
+ $rclist = array_values($rclist);
4689
+ return true;
4690
+ }
4691
+ }
4692
+
4693
+ return false;
4694
+ }
4695
+
4696
+ /**
4697
+ * Get a revoked certificate.
4698
+ *
4699
+ * @param string $serial
4700
+ * @access public
4701
+ * @return mixed
4702
+ */
4703
+ function getRevoked($serial)
4704
+ {
4705
+ if (is_array($rclist = $this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
4706
+ if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
4707
+ return $rclist[$i];
4708
+ }
4709
+ }
4710
+
4711
+ return false;
4712
+ }
4713
+
4714
+ /**
4715
+ * List revoked certificates
4716
+ *
4717
+ * @param array $crl optional
4718
+ * @access public
4719
+ * @return array
4720
+ */
4721
+ function listRevoked($crl = null)
4722
+ {
4723
+ if (!isset($crl)) {
4724
+ $crl = $this->currentCert;
4725
+ }
4726
+
4727
+ if (!isset($crl['tbsCertList'])) {
4728
+ return false;
4729
+ }
4730
+
4731
+ $result = array();
4732
+
4733
+ if (is_array($rclist =