PageRenderTime 60ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/www/system/library/Zend/Filter/Encrypt/Openssl.php

https://bitbucket.org/vmihailenco/zf-blog
PHP | 492 lines | 257 code | 71 blank | 164 comment | 41 complexity | a278239f07bf27170715b41093f5a7ec MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  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@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Filter
  17. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Openssl.php 21212 2010-02-27 17:33:27Z thomas $
  20. */
  21. /**
  22. * @see Zend_Filter_Encrypt_Interface
  23. */
  24. /**
  25. * Encryption adapter for openssl
  26. *
  27. * @category Zend
  28. * @package Zend_Filter
  29. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  30. * @license http://framework.zend.com/license/new-bsd New BSD License
  31. */
  32. class Zend_Filter_Encrypt_Openssl implements Zend_Filter_Encrypt_Interface
  33. {
  34. /**
  35. * Definitions for encryption
  36. * array(
  37. * 'public' => public keys
  38. * 'private' => private keys
  39. * 'envelope' => resulting envelope keys
  40. * )
  41. */
  42. protected $_keys = array(
  43. 'public' => array(),
  44. 'private' => array(),
  45. 'envelope' => array()
  46. );
  47. /**
  48. * Internal passphrase
  49. *
  50. * @var string
  51. */
  52. protected $_passphrase;
  53. /**
  54. * Internal compression
  55. *
  56. * @var array
  57. */
  58. protected $_compression;
  59. /**
  60. * Internal create package
  61. *
  62. * @var boolean
  63. */
  64. protected $_package = false;
  65. /**
  66. * Class constructor
  67. * Available options
  68. * 'public' => public key
  69. * 'private' => private key
  70. * 'envelope' => envelope key
  71. * 'passphrase' => passphrase
  72. * 'compression' => compress value with this compression adapter
  73. * 'package' => pack envelope keys into encrypted string, simplifies decryption
  74. *
  75. * @param string|array $options Options for this adapter
  76. */
  77. public function __construct($options = array())
  78. {
  79. if (!extension_loaded('openssl')) {
  80. throw new Zend_Filter_Exception('This filter needs the openssl extension');
  81. }
  82. if ($options instanceof Zend_Config) {
  83. $options = $options->toArray();
  84. }
  85. if (!is_array($options)) {
  86. $options = array('public' => $options);
  87. }
  88. if (array_key_exists('passphrase', $options)) {
  89. $this->setPassphrase($options['passphrase']);
  90. unset($options['passphrase']);
  91. }
  92. if (array_key_exists('compression', $options)) {
  93. $this->setCompression($options['compression']);
  94. unset($options['compress']);
  95. }
  96. if (array_key_exists('package', $options)) {
  97. $this->setPackage($options['package']);
  98. unset($options['package']);
  99. }
  100. $this->_setKeys($options);
  101. }
  102. /**
  103. * Sets the encryption keys
  104. *
  105. * @param string|array $keys Key with type association
  106. * @return Zend_Filter_Encrypt_Openssl
  107. */
  108. protected function _setKeys($keys)
  109. {
  110. if (!is_array($keys)) {
  111. throw new Zend_Filter_Exception('Invalid options argument provided to filter');
  112. }
  113. foreach ($keys as $type => $key) {
  114. if (is_file($key) and is_readable($key)) {
  115. $file = fopen($key, 'r');
  116. $cert = fread($file, 8192);
  117. fclose($file);
  118. } else {
  119. $cert = $key;
  120. $key = count($this->_keys[$type]);
  121. }
  122. switch ($type) {
  123. case 'public':
  124. $test = openssl_pkey_get_public($cert);
  125. if ($test === false) {
  126. throw new Zend_Filter_Exception("Public key '{$cert}' not valid");
  127. }
  128. openssl_free_key($test);
  129. $this->_keys['public'][$key] = $cert;
  130. break;
  131. case 'private':
  132. $test = openssl_pkey_get_private($cert, $this->_passphrase);
  133. if ($test === false) {
  134. throw new Zend_Filter_Exception("Private key '{$cert}' not valid");
  135. }
  136. openssl_free_key($test);
  137. $this->_keys['private'][$key] = $cert;
  138. break;
  139. case 'envelope':
  140. $this->_keys['envelope'][$key] = $cert;
  141. break;
  142. default:
  143. break;
  144. }
  145. }
  146. return $this;
  147. }
  148. /**
  149. * Returns all public keys
  150. *
  151. * @return array
  152. */
  153. public function getPublicKey()
  154. {
  155. $key = $this->_keys['public'];
  156. return $key;
  157. }
  158. /**
  159. * Sets public keys
  160. *
  161. * @param string|array $key Public keys
  162. * @return Zend_Filter_Encrypt_Openssl
  163. */
  164. public function setPublicKey($key)
  165. {
  166. if (is_array($key)) {
  167. foreach($key as $type => $option) {
  168. if ($type !== 'public') {
  169. $key['public'] = $option;
  170. unset($key[$type]);
  171. }
  172. }
  173. } else {
  174. $key = array('public' => $key);
  175. }
  176. return $this->_setKeys($key);
  177. }
  178. /**
  179. * Returns all private keys
  180. *
  181. * @return array
  182. */
  183. public function getPrivateKey()
  184. {
  185. $key = $this->_keys['private'];
  186. return $key;
  187. }
  188. /**
  189. * Sets private keys
  190. *
  191. * @param string $key Private key
  192. * @param string $passphrase
  193. * @return Zend_Filter_Encrypt_Openssl
  194. */
  195. public function setPrivateKey($key, $passphrase = null)
  196. {
  197. if (is_array($key)) {
  198. foreach($key as $type => $option) {
  199. if ($type !== 'private') {
  200. $key['private'] = $option;
  201. unset($key[$type]);
  202. }
  203. }
  204. } else {
  205. $key = array('private' => $key);
  206. }
  207. if ($passphrase !== null) {
  208. $this->setPassphrase($passphrase);
  209. }
  210. return $this->_setKeys($key);
  211. }
  212. /**
  213. * Returns all envelope keys
  214. *
  215. * @return array
  216. */
  217. public function getEnvelopeKey()
  218. {
  219. $key = $this->_keys['envelope'];
  220. return $key;
  221. }
  222. /**
  223. * Sets envelope keys
  224. *
  225. * @param string|array $options Envelope keys
  226. * @return Zend_Filter_Encrypt_Openssl
  227. */
  228. public function setEnvelopeKey($key)
  229. {
  230. if (is_array($key)) {
  231. foreach($key as $type => $option) {
  232. if ($type !== 'envelope') {
  233. $key['envelope'] = $option;
  234. unset($key[$type]);
  235. }
  236. }
  237. } else {
  238. $key = array('envelope' => $key);
  239. }
  240. return $this->_setKeys($key);
  241. }
  242. /**
  243. * Returns the passphrase
  244. *
  245. * @return string
  246. */
  247. public function getPassphrase()
  248. {
  249. return $this->_passphrase;
  250. }
  251. /**
  252. * Sets a new passphrase
  253. *
  254. * @param string $passphrase
  255. * @return Zend_Filter_Encrypt_Openssl
  256. */
  257. public function setPassphrase($passphrase)
  258. {
  259. $this->_passphrase = $passphrase;
  260. return $this;
  261. }
  262. /**
  263. * Returns the compression
  264. *
  265. * @return array
  266. */
  267. public function getCompression()
  268. {
  269. return $this->_compression;
  270. }
  271. /**
  272. * Sets a internal compression for values to encrypt
  273. *
  274. * @param string|array $compression
  275. * @return Zend_Filter_Encrypt_Openssl
  276. */
  277. public function setCompression($compression)
  278. {
  279. if (is_string($this->_compression)) {
  280. $compression = array('adapter' => $compression);
  281. }
  282. $this->_compression = $compression;
  283. return $this;
  284. }
  285. /**
  286. * Returns if header should be packaged
  287. *
  288. * @return boolean
  289. */
  290. public function getPackage()
  291. {
  292. return $this->_package;
  293. }
  294. /**
  295. * Sets if the envelope keys should be included in the encrypted value
  296. *
  297. * @param boolean $package
  298. * @return Zend_Filter_Encrypt_Openssl
  299. */
  300. public function setPackage($package)
  301. {
  302. $this->_package = (boolean) $package;
  303. return $this;
  304. }
  305. /**
  306. * Encrypts $value with the defined settings
  307. * Note that you also need the "encrypted" keys to be able to decrypt
  308. *
  309. * @param string $value Content to encrypt
  310. * @return string The encrypted content
  311. * @throws Zend_Filter_Exception
  312. */
  313. public function encrypt($value)
  314. {
  315. $encrypted = array();
  316. $encryptedkeys = array();
  317. if (count($this->_keys['public']) == 0) {
  318. throw new Zend_Filter_Exception('Openssl can not encrypt without public keys');
  319. }
  320. $keys = array();
  321. $fingerprints = array();
  322. $count = -1;
  323. foreach($this->_keys['public'] as $key => $cert) {
  324. $keys[$key] = openssl_pkey_get_public($cert);
  325. if ($this->_package) {
  326. $details = openssl_pkey_get_details($keys[$key]);
  327. if ($details === false) {
  328. $details = array('key' => 'ZendFramework');
  329. }
  330. ++$count;
  331. $fingerprints[$count] = md5($details['key']);
  332. }
  333. }
  334. // compress prior to encryption
  335. if (!empty($this->_compression)) {
  336. $compress = new Zend_Filter_Compress($this->_compression);
  337. $value = $compress->filter($value);
  338. }
  339. $crypt = openssl_seal($value, $encrypted, $encryptedkeys, $keys);
  340. foreach ($keys as $key) {
  341. openssl_free_key($key);
  342. }
  343. if ($crypt === false) {
  344. throw new Zend_Filter_Exception('Openssl was not able to encrypt your content with the given options');
  345. }
  346. $this->_keys['envelope'] = $encryptedkeys;
  347. // Pack data and envelope keys into single string
  348. if ($this->_package) {
  349. $header = pack('n', count($this->_keys['envelope']));
  350. foreach($this->_keys['envelope'] as $key => $envKey) {
  351. $header .= pack('H32n', $fingerprints[$key], strlen($envKey)) . $envKey;
  352. }
  353. $encrypted = $header . $encrypted;
  354. }
  355. return $encrypted;
  356. }
  357. /**
  358. * Defined by Zend_Filter_Interface
  359. *
  360. * Decrypts $value with the defined settings
  361. *
  362. * @param string $value Content to decrypt
  363. * @return string The decrypted content
  364. * @throws Zend_Filter_Exception
  365. */
  366. public function decrypt($value)
  367. {
  368. $decrypted = "";
  369. $envelope = current($this->getEnvelopeKey());
  370. if (count($this->_keys['private']) !== 1) {
  371. throw new Zend_Filter_Exception('Please give a private key for decryption with Openssl');
  372. }
  373. if (!$this->_package && empty($envelope)) {
  374. throw new Zend_Filter_Exception('Please give a envelope key for decryption with Openssl');
  375. }
  376. foreach($this->_keys['private'] as $key => $cert) {
  377. $keys = openssl_pkey_get_private($cert, $this->getPassphrase());
  378. }
  379. if ($this->_package) {
  380. $details = openssl_pkey_get_details($keys);
  381. if ($details !== false) {
  382. $fingerprint = md5($details['key']);
  383. } else {
  384. $fingerprint = md5("ZendFramework");
  385. }
  386. $count = unpack('ncount', $value);
  387. $count = $count['count'];
  388. $length = 2;
  389. for($i = $count; $i > 0; --$i) {
  390. $header = unpack('H32print/nsize', substr($value, $length, 18));
  391. $length += 18;
  392. if ($header['print'] == $fingerprint) {
  393. $envelope = substr($value, $length, $header['size']);
  394. }
  395. $length += $header['size'];
  396. }
  397. // remainder of string is the value to decrypt
  398. $value = substr($value, $length);
  399. }
  400. $crypt = openssl_open($value, $decrypted, $envelope, $keys);
  401. openssl_free_key($keys);
  402. if ($crypt === false) {
  403. throw new Zend_Filter_Exception('Openssl was not able to decrypt you content with the given options');
  404. }
  405. // decompress after decryption
  406. if (!empty($this->_compression)) {
  407. $decompress = new Zend_Filter_Decompress($this->_compression);
  408. $decrypted = $decompress->filter($decrypted);
  409. }
  410. return $decrypted;
  411. }
  412. /**
  413. * Returns the adapter name
  414. *
  415. * @return string
  416. */
  417. public function toString()
  418. {
  419. return 'Openssl';
  420. }
  421. }