PageRenderTime 25ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/roundcubemail-0.7.2-dep/plugins/enigma/lib/Crypt/GPG.php

#
PHP | 2542 lines | 913 code | 252 blank | 1377 comment | 147 complexity | fb0d02b23b92e09fc096e5e5f8b39f24 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * Crypt_GPG is a package to use GPG from PHP
  5. *
  6. * This package provides an object oriented interface to GNU Privacy
  7. * Guard (GPG). It requires the GPG executable to be on the system.
  8. *
  9. * Though GPG can support symmetric-key cryptography, this package is intended
  10. * only to facilitate public-key cryptography.
  11. *
  12. * This file contains the main GPG class. The class in this file lets you
  13. * encrypt, decrypt, sign and verify data; import and delete keys; and perform
  14. * other useful GPG tasks.
  15. *
  16. * Example usage:
  17. * <code>
  18. * <?php
  19. * // encrypt some data
  20. * $gpg = new Crypt_GPG();
  21. * $gpg->addEncryptKey($mySecretKeyId);
  22. * $encryptedData = $gpg->encrypt($data);
  23. * ?>
  24. * </code>
  25. *
  26. * PHP version 5
  27. *
  28. * LICENSE:
  29. *
  30. * This library is free software; you can redistribute it and/or modify
  31. * it under the terms of the GNU Lesser General Public License as
  32. * published by the Free Software Foundation; either version 2.1 of the
  33. * License, or (at your option) any later version.
  34. *
  35. * This library is distributed in the hope that it will be useful,
  36. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  38. * Lesser General Public License for more details.
  39. *
  40. * You should have received a copy of the GNU Lesser General Public
  41. * License along with this library; if not, write to the Free Software
  42. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  43. *
  44. * @category Encryption
  45. * @package Crypt_GPG
  46. * @author Nathan Fredrickson <nathan@silverorange.com>
  47. * @author Michael Gauthier <mike@silverorange.com>
  48. * @copyright 2005-2010 silverorange
  49. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  50. * @version CVS: $Id: GPG.php 302814 2010-08-26 15:43:07Z gauthierm $
  51. * @link http://pear.php.net/package/Crypt_GPG
  52. * @link http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
  53. * @link http://www.gnupg.org/
  54. */
  55. /**
  56. * Signature handler class
  57. */
  58. require_once 'Crypt/GPG/VerifyStatusHandler.php';
  59. /**
  60. * Decryption handler class
  61. */
  62. require_once 'Crypt/GPG/DecryptStatusHandler.php';
  63. /**
  64. * GPG key class
  65. */
  66. require_once 'Crypt/GPG/Key.php';
  67. /**
  68. * GPG sub-key class
  69. */
  70. require_once 'Crypt/GPG/SubKey.php';
  71. /**
  72. * GPG user id class
  73. */
  74. require_once 'Crypt/GPG/UserId.php';
  75. /**
  76. * GPG process and I/O engine class
  77. */
  78. require_once 'Crypt/GPG/Engine.php';
  79. /**
  80. * GPG exception classes
  81. */
  82. require_once 'Crypt/GPG/Exceptions.php';
  83. // {{{ class Crypt_GPG
  84. /**
  85. * A class to use GPG from PHP
  86. *
  87. * This class provides an object oriented interface to GNU Privacy Guard (GPG).
  88. *
  89. * Though GPG can support symmetric-key cryptography, this class is intended
  90. * only to facilitate public-key cryptography.
  91. *
  92. * @category Encryption
  93. * @package Crypt_GPG
  94. * @author Nathan Fredrickson <nathan@silverorange.com>
  95. * @author Michael Gauthier <mike@silverorange.com>
  96. * @copyright 2005-2010 silverorange
  97. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  98. * @link http://pear.php.net/package/Crypt_GPG
  99. * @link http://www.gnupg.org/
  100. */
  101. class Crypt_GPG
  102. {
  103. // {{{ class error constants
  104. /**
  105. * Error code returned when there is no error.
  106. */
  107. const ERROR_NONE = 0;
  108. /**
  109. * Error code returned when an unknown or unhandled error occurs.
  110. */
  111. const ERROR_UNKNOWN = 1;
  112. /**
  113. * Error code returned when a bad passphrase is used.
  114. */
  115. const ERROR_BAD_PASSPHRASE = 2;
  116. /**
  117. * Error code returned when a required passphrase is missing.
  118. */
  119. const ERROR_MISSING_PASSPHRASE = 3;
  120. /**
  121. * Error code returned when a key that is already in the keyring is
  122. * imported.
  123. */
  124. const ERROR_DUPLICATE_KEY = 4;
  125. /**
  126. * Error code returned the required data is missing for an operation.
  127. *
  128. * This could be missing key data, missing encrypted data or missing
  129. * signature data.
  130. */
  131. const ERROR_NO_DATA = 5;
  132. /**
  133. * Error code returned when an unsigned key is used.
  134. */
  135. const ERROR_UNSIGNED_KEY = 6;
  136. /**
  137. * Error code returned when a key that is not self-signed is used.
  138. */
  139. const ERROR_NOT_SELF_SIGNED = 7;
  140. /**
  141. * Error code returned when a public or private key that is not in the
  142. * keyring is used.
  143. */
  144. const ERROR_KEY_NOT_FOUND = 8;
  145. /**
  146. * Error code returned when an attempt to delete public key having a
  147. * private key is made.
  148. */
  149. const ERROR_DELETE_PRIVATE_KEY = 9;
  150. /**
  151. * Error code returned when one or more bad signatures are detected.
  152. */
  153. const ERROR_BAD_SIGNATURE = 10;
  154. /**
  155. * Error code returned when there is a problem reading GnuPG data files.
  156. */
  157. const ERROR_FILE_PERMISSIONS = 11;
  158. // }}}
  159. // {{{ class constants for data signing modes
  160. /**
  161. * Signing mode for normal signing of data. The signed message will not
  162. * be readable without special software.
  163. *
  164. * This is the default signing mode.
  165. *
  166. * @see Crypt_GPG::sign()
  167. * @see Crypt_GPG::signFile()
  168. */
  169. const SIGN_MODE_NORMAL = 1;
  170. /**
  171. * Signing mode for clearsigning data. Clearsigned signatures are ASCII
  172. * armored data and are readable without special software. If the signed
  173. * message is unencrypted, the message will still be readable. The message
  174. * text will be in the original encoding.
  175. *
  176. * @see Crypt_GPG::sign()
  177. * @see Crypt_GPG::signFile()
  178. */
  179. const SIGN_MODE_CLEAR = 2;
  180. /**
  181. * Signing mode for creating a detached signature. When using detached
  182. * signatures, only the signature data is returned. The original message
  183. * text may be distributed separately from the signature data. This is
  184. * useful for miltipart/signed email messages as per
  185. * {@link http://www.ietf.org/rfc/rfc3156.txt RFC 3156}.
  186. *
  187. * @see Crypt_GPG::sign()
  188. * @see Crypt_GPG::signFile()
  189. */
  190. const SIGN_MODE_DETACHED = 3;
  191. // }}}
  192. // {{{ class constants for fingerprint formats
  193. /**
  194. * No formatting is performed.
  195. *
  196. * Example: C3BC615AD9C766E5A85C1F2716D27458B1BBA1C4
  197. *
  198. * @see Crypt_GPG::getFingerprint()
  199. */
  200. const FORMAT_NONE = 1;
  201. /**
  202. * Fingerprint is formatted in the format used by the GnuPG gpg command's
  203. * default output.
  204. *
  205. * Example: C3BC 615A D9C7 66E5 A85C 1F27 16D2 7458 B1BB A1C4
  206. *
  207. * @see Crypt_GPG::getFingerprint()
  208. */
  209. const FORMAT_CANONICAL = 2;
  210. /**
  211. * Fingerprint is formatted in the format used when displaying X.509
  212. * certificates
  213. *
  214. * Example: C3:BC:61:5A:D9:C7:66:E5:A8:5C:1F:27:16:D2:74:58:B1:BB:A1:C4
  215. *
  216. * @see Crypt_GPG::getFingerprint()
  217. */
  218. const FORMAT_X509 = 3;
  219. // }}}
  220. // {{{ other class constants
  221. /**
  222. * URI at which package bugs may be reported.
  223. */
  224. const BUG_URI = 'http://pear.php.net/bugs/report.php?package=Crypt_GPG';
  225. // }}}
  226. // {{{ protected class properties
  227. /**
  228. * Engine used to control the GPG subprocess
  229. *
  230. * @var Crypt_GPG_Engine
  231. *
  232. * @see Crypt_GPG::setEngine()
  233. */
  234. protected $engine = null;
  235. /**
  236. * Keys used to encrypt
  237. *
  238. * The array is of the form:
  239. * <code>
  240. * array(
  241. * $key_id => array(
  242. * 'fingerprint' => $fingerprint,
  243. * 'passphrase' => null
  244. * )
  245. * );
  246. * </code>
  247. *
  248. * @var array
  249. * @see Crypt_GPG::addEncryptKey()
  250. * @see Crypt_GPG::clearEncryptKeys()
  251. */
  252. protected $encryptKeys = array();
  253. /**
  254. * Keys used to decrypt
  255. *
  256. * The array is of the form:
  257. * <code>
  258. * array(
  259. * $key_id => array(
  260. * 'fingerprint' => $fingerprint,
  261. * 'passphrase' => $passphrase
  262. * )
  263. * );
  264. * </code>
  265. *
  266. * @var array
  267. * @see Crypt_GPG::addSignKey()
  268. * @see Crypt_GPG::clearSignKeys()
  269. */
  270. protected $signKeys = array();
  271. /**
  272. * Keys used to sign
  273. *
  274. * The array is of the form:
  275. * <code>
  276. * array(
  277. * $key_id => array(
  278. * 'fingerprint' => $fingerprint,
  279. * 'passphrase' => $passphrase
  280. * )
  281. * );
  282. * </code>
  283. *
  284. * @var array
  285. * @see Crypt_GPG::addDecryptKey()
  286. * @see Crypt_GPG::clearDecryptKeys()
  287. */
  288. protected $decryptKeys = array();
  289. // }}}
  290. // {{{ __construct()
  291. /**
  292. * Creates a new GPG object
  293. *
  294. * Available options are:
  295. *
  296. * - <kbd>string homedir</kbd> - the directory where the GPG
  297. * keyring files are stored. If not
  298. * specified, Crypt_GPG uses the
  299. * default of <kbd>~/.gnupg</kbd>.
  300. * - <kbd>string publicKeyring</kbd> - the file path of the public
  301. * keyring. Use this if the public
  302. * keyring is not in the homedir, or
  303. * if the keyring is in a directory
  304. * not writable by the process
  305. * invoking GPG (like Apache). Then
  306. * you can specify the path to the
  307. * keyring with this option
  308. * (/foo/bar/pubring.gpg), and specify
  309. * a writable directory (like /tmp)
  310. * using the <i>homedir</i> option.
  311. * - <kbd>string privateKeyring</kbd> - the file path of the private
  312. * keyring. Use this if the private
  313. * keyring is not in the homedir, or
  314. * if the keyring is in a directory
  315. * not writable by the process
  316. * invoking GPG (like Apache). Then
  317. * you can specify the path to the
  318. * keyring with this option
  319. * (/foo/bar/secring.gpg), and specify
  320. * a writable directory (like /tmp)
  321. * using the <i>homedir</i> option.
  322. * - <kbd>string trustDb</kbd> - the file path of the web-of-trust
  323. * database. Use this if the trust
  324. * database is not in the homedir, or
  325. * if the database is in a directory
  326. * not writable by the process
  327. * invoking GPG (like Apache). Then
  328. * you can specify the path to the
  329. * trust database with this option
  330. * (/foo/bar/trustdb.gpg), and specify
  331. * a writable directory (like /tmp)
  332. * using the <i>homedir</i> option.
  333. * - <kbd>string binary</kbd> - the location of the GPG binary. If
  334. * not specified, the driver attempts
  335. * to auto-detect the GPG binary
  336. * location using a list of known
  337. * default locations for the current
  338. * operating system. The option
  339. * <kbd>gpgBinary</kbd> is a
  340. * deprecated alias for this option.
  341. * - <kbd>boolean debug</kbd> - whether or not to use debug mode.
  342. * When debug mode is on, all
  343. * communication to and from the GPG
  344. * subprocess is logged. This can be
  345. *
  346. * @param array $options optional. An array of options used to create the
  347. * GPG object. All options are optional and are
  348. * represented as key-value pairs.
  349. *
  350. * @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
  351. * and cannot be created. This can happen if <kbd>homedir</kbd> is
  352. * not specified, Crypt_GPG is run as the web user, and the web
  353. * user has no home directory. This exception is also thrown if any
  354. * of the options <kbd>publicKeyring</kbd>,
  355. * <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
  356. * specified but the files do not exist or are are not readable.
  357. * This can happen if the user running the Crypt_GPG process (for
  358. * example, the Apache user) does not have permission to read the
  359. * files.
  360. *
  361. * @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
  362. * if no <kbd>binary</kbd> is provided and no suitable binary could
  363. * be found.
  364. */
  365. public function __construct(array $options = array())
  366. {
  367. $this->setEngine(new Crypt_GPG_Engine($options));
  368. }
  369. // }}}
  370. // {{{ importKey()
  371. /**
  372. * Imports a public or private key into the keyring
  373. *
  374. * Keys may be removed from the keyring using
  375. * {@link Crypt_GPG::deletePublicKey()} or
  376. * {@link Crypt_GPG::deletePrivateKey()}.
  377. *
  378. * @param string $data the key data to be imported.
  379. *
  380. * @return array an associative array containing the following elements:
  381. * - <kbd>fingerprint</kbd> - the fingerprint of the
  382. * imported key,
  383. * - <kbd>public_imported</kbd> - the number of public
  384. * keys imported,
  385. * - <kbd>public_unchanged</kbd> - the number of unchanged
  386. * public keys,
  387. * - <kbd>private_imported</kbd> - the number of private
  388. * keys imported,
  389. * - <kbd>private_unchanged</kbd> - the number of unchanged
  390. * private keys.
  391. *
  392. * @throws Crypt_GPG_NoDataException if the key data is missing or if the
  393. * data is is not valid key data.
  394. *
  395. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  396. * Use the <kbd>debug</kbd> option and file a bug report if these
  397. * exceptions occur.
  398. */
  399. public function importKey($data)
  400. {
  401. return $this->_importKey($data, false);
  402. }
  403. // }}}
  404. // {{{ importKeyFile()
  405. /**
  406. * Imports a public or private key file into the keyring
  407. *
  408. * Keys may be removed from the keyring using
  409. * {@link Crypt_GPG::deletePublicKey()} or
  410. * {@link Crypt_GPG::deletePrivateKey()}.
  411. *
  412. * @param string $filename the key file to be imported.
  413. *
  414. * @return array an associative array containing the following elements:
  415. * - <kbd>fingerprint</kbd> - the fingerprint of the
  416. * imported key,
  417. * - <kbd>public_imported</kbd> - the number of public
  418. * keys imported,
  419. * - <kbd>public_unchanged</kbd> - the number of unchanged
  420. * public keys,
  421. * - <kbd>private_imported</kbd> - the number of private
  422. * keys imported,
  423. * - <kbd>private_unchanged</kbd> - the number of unchanged
  424. * private keys.
  425. * private keys.
  426. *
  427. * @throws Crypt_GPG_NoDataException if the key data is missing or if the
  428. * data is is not valid key data.
  429. *
  430. * @throws Crypt_GPG_FileException if the key file is not readable.
  431. *
  432. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  433. * Use the <kbd>debug</kbd> option and file a bug report if these
  434. * exceptions occur.
  435. */
  436. public function importKeyFile($filename)
  437. {
  438. return $this->_importKey($filename, true);
  439. }
  440. // }}}
  441. // {{{ exportPublicKey()
  442. /**
  443. * Exports a public key from the keyring
  444. *
  445. * The exported key remains on the keyring. To delete the public key, use
  446. * {@link Crypt_GPG::deletePublicKey()}.
  447. *
  448. * If more than one key fingerprint is available for the specified
  449. * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
  450. * first public key is exported.
  451. *
  452. * @param string $keyId either the full uid of the public key, the email
  453. * part of the uid of the public key or the key id of
  454. * the public key. For example,
  455. * "Test User (example) <test@example.com>",
  456. * "test@example.com" or a hexadecimal string.
  457. * @param boolean $armor optional. If true, ASCII armored data is returned;
  458. * otherwise, binary data is returned. Defaults to
  459. * true.
  460. *
  461. * @return string the public key data.
  462. *
  463. * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
  464. * <kbd>$keyId</kbd> is not found.
  465. *
  466. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  467. * Use the <kbd>debug</kbd> option and file a bug report if these
  468. * exceptions occur.
  469. */
  470. public function exportPublicKey($keyId, $armor = true)
  471. {
  472. $fingerprint = $this->getFingerprint($keyId);
  473. if ($fingerprint === null) {
  474. throw new Crypt_GPG_KeyNotFoundException(
  475. 'Public key not found: ' . $keyId,
  476. Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
  477. }
  478. $keyData = '';
  479. $operation = '--export ' . escapeshellarg($fingerprint);
  480. $arguments = ($armor) ? array('--armor') : array();
  481. $this->engine->reset();
  482. $this->engine->setOutput($keyData);
  483. $this->engine->setOperation($operation, $arguments);
  484. $this->engine->run();
  485. $code = $this->engine->getErrorCode();
  486. if ($code !== Crypt_GPG::ERROR_NONE) {
  487. throw new Crypt_GPG_Exception(
  488. 'Unknown error exporting public key. Please use the ' .
  489. '\'debug\' option when creating the Crypt_GPG object, and ' .
  490. 'file a bug report at ' . self::BUG_URI, $code);
  491. }
  492. return $keyData;
  493. }
  494. // }}}
  495. // {{{ deletePublicKey()
  496. /**
  497. * Deletes a public key from the keyring
  498. *
  499. * If more than one key fingerprint is available for the specified
  500. * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
  501. * first public key is deleted.
  502. *
  503. * The private key must be deleted first or an exception will be thrown.
  504. * See {@link Crypt_GPG::deletePrivateKey()}.
  505. *
  506. * @param string $keyId either the full uid of the public key, the email
  507. * part of the uid of the public key or the key id of
  508. * the public key. For example,
  509. * "Test User (example) <test@example.com>",
  510. * "test@example.com" or a hexadecimal string.
  511. *
  512. * @return void
  513. *
  514. * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
  515. * <kbd>$keyId</kbd> is not found.
  516. *
  517. * @throws Crypt_GPG_DeletePrivateKeyException if the specified public key
  518. * has an associated private key on the keyring. The private key
  519. * must be deleted first.
  520. *
  521. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  522. * Use the <kbd>debug</kbd> option and file a bug report if these
  523. * exceptions occur.
  524. */
  525. public function deletePublicKey($keyId)
  526. {
  527. $fingerprint = $this->getFingerprint($keyId);
  528. if ($fingerprint === null) {
  529. throw new Crypt_GPG_KeyNotFoundException(
  530. 'Public key not found: ' . $keyId,
  531. Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
  532. }
  533. $operation = '--delete-key ' . escapeshellarg($fingerprint);
  534. $arguments = array(
  535. '--batch',
  536. '--yes'
  537. );
  538. $this->engine->reset();
  539. $this->engine->setOperation($operation, $arguments);
  540. $this->engine->run();
  541. $code = $this->engine->getErrorCode();
  542. switch ($code) {
  543. case Crypt_GPG::ERROR_NONE:
  544. break;
  545. case Crypt_GPG::ERROR_DELETE_PRIVATE_KEY:
  546. throw new Crypt_GPG_DeletePrivateKeyException(
  547. 'Private key must be deleted before public key can be ' .
  548. 'deleted.', $code, $keyId);
  549. default:
  550. throw new Crypt_GPG_Exception(
  551. 'Unknown error deleting public key. Please use the ' .
  552. '\'debug\' option when creating the Crypt_GPG object, and ' .
  553. 'file a bug report at ' . self::BUG_URI, $code);
  554. }
  555. }
  556. // }}}
  557. // {{{ deletePrivateKey()
  558. /**
  559. * Deletes a private key from the keyring
  560. *
  561. * If more than one key fingerprint is available for the specified
  562. * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
  563. * first private key is deleted.
  564. *
  565. * Calls GPG with the <kbd>--delete-secret-key</kbd> command.
  566. *
  567. * @param string $keyId either the full uid of the private key, the email
  568. * part of the uid of the private key or the key id of
  569. * the private key. For example,
  570. * "Test User (example) <test@example.com>",
  571. * "test@example.com" or a hexadecimal string.
  572. *
  573. * @return void
  574. *
  575. * @throws Crypt_GPG_KeyNotFoundException if a private key with the given
  576. * <kbd>$keyId</kbd> is not found.
  577. *
  578. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  579. * Use the <kbd>debug</kbd> option and file a bug report if these
  580. * exceptions occur.
  581. */
  582. public function deletePrivateKey($keyId)
  583. {
  584. $fingerprint = $this->getFingerprint($keyId);
  585. if ($fingerprint === null) {
  586. throw new Crypt_GPG_KeyNotFoundException(
  587. 'Private key not found: ' . $keyId,
  588. Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
  589. }
  590. $operation = '--delete-secret-key ' . escapeshellarg($fingerprint);
  591. $arguments = array(
  592. '--batch',
  593. '--yes'
  594. );
  595. $this->engine->reset();
  596. $this->engine->setOperation($operation, $arguments);
  597. $this->engine->run();
  598. $code = $this->engine->getErrorCode();
  599. switch ($code) {
  600. case Crypt_GPG::ERROR_NONE:
  601. break;
  602. case Crypt_GPG::ERROR_KEY_NOT_FOUND:
  603. throw new Crypt_GPG_KeyNotFoundException(
  604. 'Private key not found: ' . $keyId,
  605. $code, $keyId);
  606. default:
  607. throw new Crypt_GPG_Exception(
  608. 'Unknown error deleting private key. Please use the ' .
  609. '\'debug\' option when creating the Crypt_GPG object, and ' .
  610. 'file a bug report at ' . self::BUG_URI, $code);
  611. }
  612. }
  613. // }}}
  614. // {{{ getKeys()
  615. /**
  616. * Gets the available keys in the keyring
  617. *
  618. * Calls GPG with the <kbd>--list-keys</kbd> command and grabs keys. See
  619. * the first section of <b>doc/DETAILS</b> in the
  620. * {@link http://www.gnupg.org/download/ GPG package} for a detailed
  621. * description of how the GPG command output is parsed.
  622. *
  623. * @param string $keyId optional. Only keys with that match the specified
  624. * pattern are returned. The pattern may be part of
  625. * a user id, a key id or a key fingerprint. If not
  626. * specified, all keys are returned.
  627. *
  628. * @return array an array of {@link Crypt_GPG_Key} objects. If no keys
  629. * match the specified <kbd>$keyId</kbd> an empty array is
  630. * returned.
  631. *
  632. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  633. * Use the <kbd>debug</kbd> option and file a bug report if these
  634. * exceptions occur.
  635. *
  636. * @see Crypt_GPG_Key
  637. */
  638. public function getKeys($keyId = '')
  639. {
  640. // get private key fingerprints
  641. if ($keyId == '') {
  642. $operation = '--list-secret-keys';
  643. } else {
  644. $operation = '--list-secret-keys ' . escapeshellarg($keyId);
  645. }
  646. // According to The file 'doc/DETAILS' in the GnuPG distribution, using
  647. // double '--with-fingerprint' also prints the fingerprint for subkeys.
  648. $arguments = array(
  649. '--with-colons',
  650. '--with-fingerprint',
  651. '--with-fingerprint',
  652. '--fixed-list-mode'
  653. );
  654. $output = '';
  655. $this->engine->reset();
  656. $this->engine->setOutput($output);
  657. $this->engine->setOperation($operation, $arguments);
  658. $this->engine->run();
  659. $code = $this->engine->getErrorCode();
  660. switch ($code) {
  661. case Crypt_GPG::ERROR_NONE:
  662. case Crypt_GPG::ERROR_KEY_NOT_FOUND:
  663. // ignore not found key errors
  664. break;
  665. case Crypt_GPG::ERROR_FILE_PERMISSIONS:
  666. $filename = $this->engine->getErrorFilename();
  667. if ($filename) {
  668. throw new Crypt_GPG_FileException(sprintf(
  669. 'Error reading GnuPG data file \'%s\'. Check to make ' .
  670. 'sure it is readable by the current user.', $filename),
  671. $code, $filename);
  672. }
  673. throw new Crypt_GPG_FileException(
  674. 'Error reading GnuPG data file. Check to make GnuPG data ' .
  675. 'files are readable by the current user.', $code);
  676. default:
  677. throw new Crypt_GPG_Exception(
  678. 'Unknown error getting keys. Please use the \'debug\' option ' .
  679. 'when creating the Crypt_GPG object, and file a bug report ' .
  680. 'at ' . self::BUG_URI, $code);
  681. }
  682. $privateKeyFingerprints = array();
  683. $lines = explode(PHP_EOL, $output);
  684. foreach ($lines as $line) {
  685. $lineExp = explode(':', $line);
  686. if ($lineExp[0] == 'fpr') {
  687. $privateKeyFingerprints[] = $lineExp[9];
  688. }
  689. }
  690. // get public keys
  691. if ($keyId == '') {
  692. $operation = '--list-public-keys';
  693. } else {
  694. $operation = '--list-public-keys ' . escapeshellarg($keyId);
  695. }
  696. $output = '';
  697. $this->engine->reset();
  698. $this->engine->setOutput($output);
  699. $this->engine->setOperation($operation, $arguments);
  700. $this->engine->run();
  701. $code = $this->engine->getErrorCode();
  702. switch ($code) {
  703. case Crypt_GPG::ERROR_NONE:
  704. case Crypt_GPG::ERROR_KEY_NOT_FOUND:
  705. // ignore not found key errors
  706. break;
  707. case Crypt_GPG::ERROR_FILE_PERMISSIONS:
  708. $filename = $this->engine->getErrorFilename();
  709. if ($filename) {
  710. throw new Crypt_GPG_FileException(sprintf(
  711. 'Error reading GnuPG data file \'%s\'. Check to make ' .
  712. 'sure it is readable by the current user.', $filename),
  713. $code, $filename);
  714. }
  715. throw new Crypt_GPG_FileException(
  716. 'Error reading GnuPG data file. Check to make GnuPG data ' .
  717. 'files are readable by the current user.', $code);
  718. default:
  719. throw new Crypt_GPG_Exception(
  720. 'Unknown error getting keys. Please use the \'debug\' option ' .
  721. 'when creating the Crypt_GPG object, and file a bug report ' .
  722. 'at ' . self::BUG_URI, $code);
  723. }
  724. $keys = array();
  725. $key = null; // current key
  726. $subKey = null; // current sub-key
  727. $lines = explode(PHP_EOL, $output);
  728. foreach ($lines as $line) {
  729. $lineExp = explode(':', $line);
  730. if ($lineExp[0] == 'pub') {
  731. // new primary key means last key should be added to the array
  732. if ($key !== null) {
  733. $keys[] = $key;
  734. }
  735. $key = new Crypt_GPG_Key();
  736. $subKey = Crypt_GPG_SubKey::parse($line);
  737. $key->addSubKey($subKey);
  738. } elseif ($lineExp[0] == 'sub') {
  739. $subKey = Crypt_GPG_SubKey::parse($line);
  740. $key->addSubKey($subKey);
  741. } elseif ($lineExp[0] == 'fpr') {
  742. $fingerprint = $lineExp[9];
  743. // set current sub-key fingerprint
  744. $subKey->setFingerprint($fingerprint);
  745. // if private key exists, set has private to true
  746. if (in_array($fingerprint, $privateKeyFingerprints)) {
  747. $subKey->setHasPrivate(true);
  748. }
  749. } elseif ($lineExp[0] == 'uid') {
  750. $string = stripcslashes($lineExp[9]); // as per documentation
  751. $userId = new Crypt_GPG_UserId($string);
  752. if ($lineExp[1] == 'r') {
  753. $userId->setRevoked(true);
  754. }
  755. $key->addUserId($userId);
  756. }
  757. }
  758. // add last key
  759. if ($key !== null) {
  760. $keys[] = $key;
  761. }
  762. return $keys;
  763. }
  764. // }}}
  765. // {{{ getFingerprint()
  766. /**
  767. * Gets a key fingerprint from the keyring
  768. *
  769. * If more than one key fingerprint is available (for example, if you use
  770. * a non-unique user id) only the first key fingerprint is returned.
  771. *
  772. * Calls the GPG <kbd>--list-keys</kbd> command with the
  773. * <kbd>--with-fingerprint</kbd> option to retrieve a public key
  774. * fingerprint.
  775. *
  776. * @param string $keyId either the full user id of the key, the email
  777. * part of the user id of the key, or the key id of
  778. * the key. For example,
  779. * "Test User (example) <test@example.com>",
  780. * "test@example.com" or a hexadecimal string.
  781. * @param integer $format optional. How the fingerprint should be formatted.
  782. * Use {@link Crypt_GPG::FORMAT_X509} for X.509
  783. * certificate format,
  784. * {@link Crypt_GPG::FORMAT_CANONICAL} for the format
  785. * used by GnuPG output and
  786. * {@link Crypt_GPG::FORMAT_NONE} for no formatting.
  787. * Defaults to <code>Crypt_GPG::FORMAT_NONE</code>.
  788. *
  789. * @return string the fingerprint of the key, or null if no fingerprint
  790. * is found for the given <kbd>$keyId</kbd>.
  791. *
  792. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  793. * Use the <kbd>debug</kbd> option and file a bug report if these
  794. * exceptions occur.
  795. */
  796. public function getFingerprint($keyId, $format = Crypt_GPG::FORMAT_NONE)
  797. {
  798. $output = '';
  799. $operation = '--list-keys ' . escapeshellarg($keyId);
  800. $arguments = array(
  801. '--with-colons',
  802. '--with-fingerprint'
  803. );
  804. $this->engine->reset();
  805. $this->engine->setOutput($output);
  806. $this->engine->setOperation($operation, $arguments);
  807. $this->engine->run();
  808. $code = $this->engine->getErrorCode();
  809. switch ($code) {
  810. case Crypt_GPG::ERROR_NONE:
  811. case Crypt_GPG::ERROR_KEY_NOT_FOUND:
  812. // ignore not found key errors
  813. break;
  814. default:
  815. throw new Crypt_GPG_Exception(
  816. 'Unknown error getting key fingerprint. Please use the ' .
  817. '\'debug\' option when creating the Crypt_GPG object, and ' .
  818. 'file a bug report at ' . self::BUG_URI, $code);
  819. }
  820. $fingerprint = null;
  821. $lines = explode(PHP_EOL, $output);
  822. foreach ($lines as $line) {
  823. if (substr($line, 0, 3) == 'fpr') {
  824. $lineExp = explode(':', $line);
  825. $fingerprint = $lineExp[9];
  826. switch ($format) {
  827. case Crypt_GPG::FORMAT_CANONICAL:
  828. $fingerprintExp = str_split($fingerprint, 4);
  829. $format = '%s %s %s %s %s %s %s %s %s %s';
  830. $fingerprint = vsprintf($format, $fingerprintExp);
  831. break;
  832. case Crypt_GPG::FORMAT_X509:
  833. $fingerprintExp = str_split($fingerprint, 2);
  834. $fingerprint = implode(':', $fingerprintExp);
  835. break;
  836. }
  837. break;
  838. }
  839. }
  840. return $fingerprint;
  841. }
  842. // }}}
  843. // {{{ encrypt()
  844. /**
  845. * Encrypts string data
  846. *
  847. * Data is ASCII armored by default but may optionally be returned as
  848. * binary.
  849. *
  850. * @param string $data the data to be encrypted.
  851. * @param boolean $armor optional. If true, ASCII armored data is returned;
  852. * otherwise, binary data is returned. Defaults to
  853. * true.
  854. *
  855. * @return string the encrypted data.
  856. *
  857. * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
  858. * See {@link Crypt_GPG::addEncryptKey()}.
  859. *
  860. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  861. * Use the <kbd>debug</kbd> option and file a bug report if these
  862. * exceptions occur.
  863. *
  864. * @sensitive $data
  865. */
  866. public function encrypt($data, $armor = true)
  867. {
  868. return $this->_encrypt($data, false, null, $armor);
  869. }
  870. // }}}
  871. // {{{ encryptFile()
  872. /**
  873. * Encrypts a file
  874. *
  875. * Encrypted data is ASCII armored by default but may optionally be saved
  876. * as binary.
  877. *
  878. * @param string $filename the filename of the file to encrypt.
  879. * @param string $encryptedFile optional. The filename of the file in
  880. * which to store the encrypted data. If null
  881. * or unspecified, the encrypted data is
  882. * returned as a string.
  883. * @param boolean $armor optional. If true, ASCII armored data is
  884. * returned; otherwise, binary data is
  885. * returned. Defaults to true.
  886. *
  887. * @return void|string if the <kbd>$encryptedFile</kbd> parameter is null,
  888. * a string containing the encrypted data is returned.
  889. *
  890. * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
  891. * See {@link Crypt_GPG::addEncryptKey()}.
  892. *
  893. * @throws Crypt_GPG_FileException if the output file is not writeable or
  894. * if the input file is not readable.
  895. *
  896. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  897. * Use the <kbd>debug</kbd> option and file a bug report if these
  898. * exceptions occur.
  899. */
  900. public function encryptFile($filename, $encryptedFile = null, $armor = true)
  901. {
  902. return $this->_encrypt($filename, true, $encryptedFile, $armor);
  903. }
  904. // }}}
  905. // {{{ encryptAndSign()
  906. /**
  907. * Encrypts and signs data
  908. *
  909. * Data is encrypted and signed in a single pass.
  910. *
  911. * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
  912. * encrypted-signed data without decrypting it at the same time. If you try
  913. * to use {@link Crypt_GPG::verify()} method on encrypted-signed data with
  914. * earlier GnuPG versions, you will get an error. Please use
  915. * {@link Crypt_GPG::decryptAndVerify()} to verify encrypted-signed data.
  916. *
  917. * @param string $data the data to be encrypted and signed.
  918. * @param boolean $armor optional. If true, ASCII armored data is returned;
  919. * otherwise, binary data is returned. Defaults to
  920. * true.
  921. *
  922. * @return string the encrypted signed data.
  923. *
  924. * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
  925. * or if no signing key is specified. See
  926. * {@link Crypt_GPG::addEncryptKey()} and
  927. * {@link Crypt_GPG::addSignKey()}.
  928. *
  929. * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
  930. * incorrect or if a required passphrase is not specified.
  931. *
  932. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  933. * Use the <kbd>debug</kbd> option and file a bug report if these
  934. * exceptions occur.
  935. *
  936. * @see Crypt_GPG::decryptAndVerify()
  937. */
  938. public function encryptAndSign($data, $armor = true)
  939. {
  940. return $this->_encryptAndSign($data, false, null, $armor);
  941. }
  942. // }}}
  943. // {{{ encryptAndSignFile()
  944. /**
  945. * Encrypts and signs a file
  946. *
  947. * The file is encrypted and signed in a single pass.
  948. *
  949. * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
  950. * encrypted-signed files without decrypting them at the same time. If you
  951. * try to use {@link Crypt_GPG::verify()} method on encrypted-signed files
  952. * with earlier GnuPG versions, you will get an error. Please use
  953. * {@link Crypt_GPG::decryptAndVerifyFile()} to verify encrypted-signed
  954. * files.
  955. *
  956. * @param string $filename the name of the file containing the data to
  957. * be encrypted and signed.
  958. * @param string $signedFile optional. The name of the file in which the
  959. * encrypted, signed data should be stored. If
  960. * null or unspecified, the encrypted, signed
  961. * data is returned as a string.
  962. * @param boolean $armor optional. If true, ASCII armored data is
  963. * returned; otherwise, binary data is returned.
  964. * Defaults to true.
  965. *
  966. * @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
  967. * string containing the encrypted, signed data is
  968. * returned.
  969. *
  970. * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
  971. * or if no signing key is specified. See
  972. * {@link Crypt_GPG::addEncryptKey()} and
  973. * {@link Crypt_GPG::addSignKey()}.
  974. *
  975. * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
  976. * incorrect or if a required passphrase is not specified.
  977. *
  978. * @throws Crypt_GPG_FileException if the output file is not writeable or
  979. * if the input file is not readable.
  980. *
  981. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  982. * Use the <kbd>debug</kbd> option and file a bug report if these
  983. * exceptions occur.
  984. *
  985. * @see Crypt_GPG::decryptAndVerifyFile()
  986. */
  987. public function encryptAndSignFile($filename, $signedFile = null,
  988. $armor = true
  989. ) {
  990. return $this->_encryptAndSign($filename, true, $signedFile, $armor);
  991. }
  992. // }}}
  993. // {{{ decrypt()
  994. /**
  995. * Decrypts string data
  996. *
  997. * This method assumes the required private key is available in the keyring
  998. * and throws an exception if the private key is not available. To add a
  999. * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
  1000. * {@link Crypt_GPG::importKeyFile()} methods.
  1001. *
  1002. * @param string $encryptedData the data to be decrypted.
  1003. *
  1004. * @return string the decrypted data.
  1005. *
  1006. * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
  1007. * decrypt the data is not in the user's keyring.
  1008. *
  1009. * @throws Crypt_GPG_NoDataException if specified data does not contain
  1010. * GPG encrypted data.
  1011. *
  1012. * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
  1013. * incorrect or if a required passphrase is not specified. See
  1014. * {@link Crypt_GPG::addDecryptKey()}.
  1015. *
  1016. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  1017. * Use the <kbd>debug</kbd> option and file a bug report if these
  1018. * exceptions occur.
  1019. */
  1020. public function decrypt($encryptedData)
  1021. {
  1022. return $this->_decrypt($encryptedData, false, null);
  1023. }
  1024. // }}}
  1025. // {{{ decryptFile()
  1026. /**
  1027. * Decrypts a file
  1028. *
  1029. * This method assumes the required private key is available in the keyring
  1030. * and throws an exception if the private key is not available. To add a
  1031. * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
  1032. * {@link Crypt_GPG::importKeyFile()} methods.
  1033. *
  1034. * @param string $encryptedFile the name of the encrypted file data to
  1035. * decrypt.
  1036. * @param string $decryptedFile optional. The name of the file to which the
  1037. * decrypted data should be written. If null
  1038. * or unspecified, the decrypted data is
  1039. * returned as a string.
  1040. *
  1041. * @return void|string if the <kbd>$decryptedFile</kbd> parameter is null,
  1042. * a string containing the decrypted data is returned.
  1043. *
  1044. * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
  1045. * decrypt the data is not in the user's keyring.
  1046. *
  1047. * @throws Crypt_GPG_NoDataException if specified data does not contain
  1048. * GPG encrypted data.
  1049. *
  1050. * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
  1051. * incorrect or if a required passphrase is not specified. See
  1052. * {@link Crypt_GPG::addDecryptKey()}.
  1053. *
  1054. * @throws Crypt_GPG_FileException if the output file is not writeable or
  1055. * if the input file is not readable.
  1056. *
  1057. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  1058. * Use the <kbd>debug</kbd> option and file a bug report if these
  1059. * exceptions occur.
  1060. */
  1061. public function decryptFile($encryptedFile, $decryptedFile = null)
  1062. {
  1063. return $this->_decrypt($encryptedFile, true, $decryptedFile);
  1064. }
  1065. // }}}
  1066. // {{{ decryptAndVerify()
  1067. /**
  1068. * Decrypts and verifies string data
  1069. *
  1070. * This method assumes the required private key is available in the keyring
  1071. * and throws an exception if the private key is not available. To add a
  1072. * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
  1073. * {@link Crypt_GPG::importKeyFile()} methods.
  1074. *
  1075. * @param string $encryptedData the encrypted, signed data to be decrypted
  1076. * and verified.
  1077. *
  1078. * @return array two element array. The array has an element 'data'
  1079. * containing the decrypted data and an element
  1080. * 'signatures' containing an array of
  1081. * {@link Crypt_GPG_Signature} objects for the signed data.
  1082. *
  1083. * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
  1084. * decrypt the data is not in the user's keyring.
  1085. *
  1086. * @throws Crypt_GPG_NoDataException if specified data does not contain
  1087. * GPG encrypted data.
  1088. *
  1089. * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
  1090. * incorrect or if a required passphrase is not specified. See
  1091. * {@link Crypt_GPG::addDecryptKey()}.
  1092. *
  1093. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  1094. * Use the <kbd>debug</kbd> option and file a bug report if these
  1095. * exceptions occur.
  1096. */
  1097. public function decryptAndVerify($encryptedData)
  1098. {
  1099. return $this->_decryptAndVerify($encryptedData, false, null);
  1100. }
  1101. // }}}
  1102. // {{{ decryptAndVerifyFile()
  1103. /**
  1104. * Decrypts and verifies a signed, encrypted file
  1105. *
  1106. * This method assumes the required private key is available in the keyring
  1107. * and throws an exception if the private key is not available. To add a
  1108. * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
  1109. * {@link Crypt_GPG::importKeyFile()} methods.
  1110. *
  1111. * @param string $encryptedFile the name of the signed, encrypted file to
  1112. * to decrypt and verify.
  1113. * @param string $decryptedFile optional. The name of the file to which the
  1114. * decrypted data should be written. If null
  1115. * or unspecified, the decrypted data is
  1116. * returned in the results array.
  1117. *
  1118. * @return array two element array. The array has an element 'data'
  1119. * containing the decrypted data and an element
  1120. * 'signatures' containing an array of
  1121. * {@link Crypt_GPG_Signature} objects for the signed data.
  1122. * If the decrypted data is written to a file, the 'data'
  1123. * element is null.
  1124. *
  1125. * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
  1126. * decrypt the data is not in the user's keyring.
  1127. *
  1128. * @throws Crypt_GPG_NoDataException if specified data does not contain
  1129. * GPG encrypted data.
  1130. *
  1131. * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
  1132. * incorrect or if a required passphrase is not specified. See
  1133. * {@link Crypt_GPG::addDecryptKey()}.
  1134. *
  1135. * @throws Crypt_GPG_FileException if the output file is not writeable or
  1136. * if the input file is not readable.
  1137. *
  1138. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  1139. * Use the <kbd>debug</kbd> option and file a bug report if these
  1140. * exceptions occur.
  1141. */
  1142. public function decryptAndVerifyFile($encryptedFile, $decryptedFile = null)
  1143. {
  1144. return $this->_decryptAndVerify($encryptedFile, true, $decryptedFile);
  1145. }
  1146. // }}}
  1147. // {{{ sign()
  1148. /**
  1149. * Signs data
  1150. *
  1151. * Data may be signed using any one of the three available signing modes:
  1152. * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
  1153. * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
  1154. * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
  1155. *
  1156. * @param string $data the data to be signed.
  1157. * @param boolean $mode optional. The data signing mode to use. Should
  1158. * be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
  1159. * {@link Crypt_GPG::SIGN_MODE_CLEAR} or
  1160. * {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
  1161. * specified, defaults to
  1162. * <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
  1163. * @param boolean $armor optional. If true, ASCII armored data is
  1164. * returned; otherwise, binary data is returned.
  1165. * Defaults to true. This has no effect if the
  1166. * mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
  1167. * used.
  1168. * @param boolean $textmode optional. If true, line-breaks in signed data
  1169. * are normalized. Use this option when signing
  1170. * e-mail, or for greater compatibility between
  1171. * systems with different line-break formats.
  1172. * Defaults to false. This has no effect if the
  1173. * mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
  1174. * used as clear-signing always uses textmode.
  1175. *
  1176. * @return string the signed data, or the signature data if a detached
  1177. * signature is requested.
  1178. *
  1179. * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
  1180. * See {@link Crypt_GPG::addSignKey()}.
  1181. *
  1182. * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
  1183. * incorrect or if a required passphrase is not specified.
  1184. *
  1185. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  1186. * Use the <kbd>debug</kbd> option and file a bug report if these
  1187. * exceptions occur.
  1188. */
  1189. public function sign($data, $mode = Crypt_GPG::SIGN_MODE_NORMAL,
  1190. $armor = true, $textmode = false
  1191. ) {
  1192. return $this->_sign($data, false, null, $mode, $armor, $textmode);
  1193. }
  1194. // }}}

Large files files are truncated, but you can click here to view the full file