You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

KeyGenerator.php 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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 file contains an object that handles GnuPG key generation.
  7. *
  8. * PHP version 5
  9. *
  10. * LICENSE:
  11. *
  12. * This library is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU Lesser General Public License as
  14. * published by the Free Software Foundation; either version 2.1 of the
  15. * License, or (at your option) any later version.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Lesser General Public
  23. * License along with this library; if not, see
  24. * <http://www.gnu.org/licenses/>
  25. *
  26. * @category Encryption
  27. * @package Crypt_GPG
  28. * @author Michael Gauthier <mike@silverorange.com>
  29. * @copyright 2011-2013 silverorange
  30. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  31. * @link http://pear.php.net/package/Crypt_GPG
  32. * @link http://www.gnupg.org/
  33. */
  34. /**
  35. * Base class for GPG methods
  36. */
  37. require_once 'Crypt/GPGAbstract.php';
  38. // {{{ class Crypt_GPG_KeyGenerator
  39. /**
  40. * GnuPG key generator
  41. *
  42. * This class provides an object oriented interface for generating keys with
  43. * the GNU Privacy Guard (GPG).
  44. *
  45. * Secure key generation requires true random numbers, and as such can be slow.
  46. * If the operating system runs out of entropy, key generation will block until
  47. * more entropy is available.
  48. *
  49. * If quick key generation is important, a hardware entropy generator, or an
  50. * entropy gathering daemon may be installed. For example, administrators of
  51. * Debian systems may want to install the 'randomsound' package.
  52. *
  53. * This class uses the experimental automated key generation support available
  54. * in GnuPG. See <b>doc/DETAILS</b> in the
  55. * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
  56. * information on the key generation format.
  57. *
  58. * @category Encryption
  59. * @package Crypt_GPG
  60. * @author Nathan Fredrickson <nathan@silverorange.com>
  61. * @author Michael Gauthier <mike@silverorange.com>
  62. * @copyright 2005-2013 silverorange
  63. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  64. * @link http://pear.php.net/package/Crypt_GPG
  65. * @link http://www.gnupg.org/
  66. */
  67. class Crypt_GPG_KeyGenerator extends Crypt_GPGAbstract
  68. {
  69. // {{{ protected properties
  70. /**
  71. * The expiration date of generated keys
  72. *
  73. * @var integer
  74. *
  75. * @see Crypt_GPG_KeyGenerator::setExpirationDate()
  76. */
  77. protected $expirationDate = 0;
  78. /**
  79. * The passphrase of generated keys
  80. *
  81. * @var string
  82. *
  83. * @see Crypt_GPG_KeyGenerator::setPassphrase()
  84. */
  85. protected $passphrase = '';
  86. /**
  87. * The algorithm for generated primary keys
  88. *
  89. * @var integer
  90. *
  91. * @see Crypt_GPG_KeyGenerator::setKeyParams()
  92. */
  93. protected $keyAlgorithm = Crypt_GPG_SubKey::ALGORITHM_DSA;
  94. /**
  95. * The size of generated primary keys
  96. *
  97. * @var integer
  98. *
  99. * @see Crypt_GPG_KeyGenerator::setKeyParams()
  100. */
  101. protected $keySize = 1024;
  102. /**
  103. * The usages of generated primary keys
  104. *
  105. * This is a bitwise combination of the usage constants in
  106. * {@link Crypt_GPG_SubKey}.
  107. *
  108. * @var integer
  109. *
  110. * @see Crypt_GPG_KeyGenerator::setKeyParams()
  111. */
  112. protected $keyUsage = 6; // USAGE_SIGN | USAGE_CERTIFY
  113. /**
  114. * The algorithm for generated sub-keys
  115. *
  116. * @var integer
  117. *
  118. * @see Crypt_GPG_KeyGenerator::setSubKeyParams()
  119. */
  120. protected $subKeyAlgorithm = Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC;
  121. /**
  122. * The size of generated sub-keys
  123. *
  124. * @var integer
  125. *
  126. * @see Crypt_GPG_KeyGenerator::setSubKeyParams()
  127. */
  128. protected $subKeySize = 2048;
  129. /**
  130. * The usages of generated sub-keys
  131. *
  132. * This is a bitwise combination of the usage constants in
  133. * {@link Crypt_GPG_SubKey}.
  134. *
  135. * @var integer
  136. *
  137. * @see Crypt_GPG_KeyGenerator::setSubKeyParams()
  138. */
  139. protected $subKeyUsage = Crypt_GPG_SubKey::USAGE_ENCRYPT;
  140. // }}}
  141. // {{{ __construct()
  142. /**
  143. * Creates a new GnuPG key generator
  144. *
  145. * Available options are:
  146. *
  147. * - <kbd>string homedir</kbd> - the directory where the GPG
  148. * keyring files are stored. If not
  149. * specified, Crypt_GPG uses the
  150. * default of <kbd>~/.gnupg</kbd>.
  151. * - <kbd>string publicKeyring</kbd> - the file path of the public
  152. * keyring. Use this if the public
  153. * keyring is not in the homedir, or
  154. * if the keyring is in a directory
  155. * not writable by the process
  156. * invoking GPG (like Apache). Then
  157. * you can specify the path to the
  158. * keyring with this option
  159. * (/foo/bar/pubring.gpg), and specify
  160. * a writable directory (like /tmp)
  161. * using the <i>homedir</i> option.
  162. * - <kbd>string privateKeyring</kbd> - the file path of the private
  163. * keyring. Use this if the private
  164. * keyring is not in the homedir, or
  165. * if the keyring is in a directory
  166. * not writable by the process
  167. * invoking GPG (like Apache). Then
  168. * you can specify the path to the
  169. * keyring with this option
  170. * (/foo/bar/secring.gpg), and specify
  171. * a writable directory (like /tmp)
  172. * using the <i>homedir</i> option.
  173. * - <kbd>string trustDb</kbd> - the file path of the web-of-trust
  174. * database. Use this if the trust
  175. * database is not in the homedir, or
  176. * if the database is in a directory
  177. * not writable by the process
  178. * invoking GPG (like Apache). Then
  179. * you can specify the path to the
  180. * trust database with this option
  181. * (/foo/bar/trustdb.gpg), and specify
  182. * a writable directory (like /tmp)
  183. * using the <i>homedir</i> option.
  184. * - <kbd>string binary</kbd> - the location of the GPG binary. If
  185. * not specified, the driver attempts
  186. * to auto-detect the GPG binary
  187. * location using a list of known
  188. * default locations for the current
  189. * operating system. The option
  190. * <kbd>gpgBinary</kbd> is a
  191. * deprecated alias for this option.
  192. * - <kbd>string agent</kbd> - the location of the GnuPG agent
  193. * binary. The gpg-agent is only
  194. * used for GnuPG 2.x. If not
  195. * specified, the engine attempts
  196. * to auto-detect the gpg-agent
  197. * binary location using a list of
  198. * know default locations for the
  199. * current operating system.
  200. * - <kbd>mixed debug</kbd> - whether or not to use debug mode.
  201. * When debug mode is on, all
  202. * communication to and from the GPG
  203. * subprocess is logged. This can be
  204. *
  205. * @param array $options optional. An array of options used to create the
  206. * GPG object. All options are optional and are
  207. * represented as key-value pairs.
  208. *
  209. * @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
  210. * and cannot be created. This can happen if <kbd>homedir</kbd> is
  211. * not specified, Crypt_GPG is run as the web user, and the web
  212. * user has no home directory. This exception is also thrown if any
  213. * of the options <kbd>publicKeyring</kbd>,
  214. * <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
  215. * specified but the files do not exist or are are not readable.
  216. * This can happen if the user running the Crypt_GPG process (for
  217. * example, the Apache user) does not have permission to read the
  218. * files.
  219. *
  220. * @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
  221. * if no <kbd>binary</kbd> is provided and no suitable binary could
  222. * be found.
  223. *
  224. * @throws PEAR_Exception if the provided <kbd>agent</kbd> is invalid, or
  225. * if no <kbd>agent</kbd> is provided and no suitable gpg-agent
  226. * cound be found.
  227. */
  228. public function __construct(array $options = array())
  229. {
  230. parent::__construct($options);
  231. }
  232. // }}}
  233. // {{{ setExpirationDate()
  234. /**
  235. * Sets the expiration date of generated keys
  236. *
  237. * @param string|integer $date either a string that may be parsed by
  238. * PHP's strtotime() function, or an integer
  239. * timestamp representing the number of seconds
  240. * since the UNIX epoch. This date must be at
  241. * least one date in the future. Keys that
  242. * expire in the past may not be generated. Use
  243. * an expiration date of 0 for keys that do not
  244. * expire.
  245. *
  246. * @throws InvalidArgumentException if the date is not a valid format, or
  247. * if the date is not at least one day in
  248. * the future, or if the date is greater
  249. * than 2038-01-19T03:14:07.
  250. *
  251. * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
  252. */
  253. public function setExpirationDate($date)
  254. {
  255. if (is_int($date) || ctype_digit(strval($date))) {
  256. $expirationDate = intval($date);
  257. } else {
  258. $expirationDate = strtotime($date);
  259. }
  260. if ($expirationDate === false) {
  261. throw new InvalidArgumentException(
  262. sprintf(
  263. 'Invalid expiration date format: "%s". Please use a ' .
  264. 'format compatible with PHP\'s strtotime().',
  265. $date
  266. )
  267. );
  268. }
  269. if ($expirationDate !== 0 && $expirationDate < time() + 86400) {
  270. throw new InvalidArgumentException(
  271. 'Expiration date must be at least a day in the future.'
  272. );
  273. }
  274. // GnuPG suffers from the 2038 bug
  275. if ($expirationDate > 2147483647) {
  276. throw new InvalidArgumentException(
  277. 'Expiration date must not be greater than 2038-01-19T03:14:07.'
  278. );
  279. }
  280. $this->expirationDate = $expirationDate;
  281. return $this;
  282. }
  283. // }}}
  284. // {{{ setPassphrase()
  285. /**
  286. * Sets the passphrase of generated keys
  287. *
  288. * @param string $passphrase the passphrase to use for generated keys. Use
  289. * null or an empty string for no passphrase.
  290. *
  291. * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
  292. */
  293. public function setPassphrase($passphrase)
  294. {
  295. $this->passphrase = strval($passphrase);
  296. return $this;
  297. }
  298. // }}}
  299. // {{{ setKeyParams()
  300. /**
  301. * Sets the parameters for the primary key of generated key-pairs
  302. *
  303. * @param integer $algorithm the algorithm used by the key. This should be
  304. * one of the Crypt_GPG_SubKey::ALGORITHM_*
  305. * constants.
  306. * @param integer $size optional. The size of the key. Different
  307. * algorithms have different size requirements.
  308. * If not specified, the default size for the
  309. * specified algorithm will be used. If an
  310. * invalid key size is used, GnuPG will do its
  311. * best to round it to a valid size.
  312. * @param integer $usage optional. A bitwise combination of key usages.
  313. * If not specified, the primary key will be used
  314. * only to sign and certify. This is the default
  315. * behavior of GnuPG in interactive mode. Use
  316. * the Crypt_GPG_SubKey::USAGE_* constants here.
  317. * The primary key may be used to certify even
  318. * if the certify usage is not specified.
  319. *
  320. * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
  321. */
  322. public function setKeyParams($algorithm, $size = 0, $usage = 0)
  323. {
  324. $algorithm = intval($algorithm);
  325. if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC) {
  326. throw new Crypt_GPG_InvalidKeyParamsException(
  327. 'Primary key algorithm must be capable of signing. The ' .
  328. 'Elgamal algorithm can only encrypt.',
  329. 0,
  330. $algorithm,
  331. $size,
  332. $usage
  333. );
  334. }
  335. if ($size != 0) {
  336. $size = intval($size);
  337. }
  338. if ($usage != 0) {
  339. $usage = intval($usage);
  340. }
  341. $usageEncrypt = Crypt_GPG_SubKey::USAGE_ENCRYPT;
  342. if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_DSA
  343. && ($usage & $usageEncrypt) === $usageEncrypt
  344. ) {
  345. throw new Crypt_GPG_InvalidKeyParamsException(
  346. 'The DSA algorithm is not capable of encrypting. Please ' .
  347. 'specify a different algorithm or do not include encryption ' .
  348. 'as a usage for the primary key.',
  349. 0,
  350. $algorithm,
  351. $size,
  352. $usage
  353. );
  354. }
  355. $this->keyAlgorithm = $algorithm;
  356. if ($size != 0) {
  357. $this->keySize = $size;
  358. }
  359. if ($usage != 0) {
  360. $this->keyUsage = $usage;
  361. }
  362. return $this;
  363. }
  364. // }}}
  365. // {{{ setSubKeyParams()
  366. /**
  367. * Sets the parameters for the sub-key of generated key-pairs
  368. *
  369. * @param integer $algorithm the algorithm used by the key. This should be
  370. * one of the Crypt_GPG_SubKey::ALGORITHM_*
  371. * constants.
  372. * @param integer $size optional. The size of the key. Different
  373. * algorithms have different size requirements.
  374. * If not specified, the default size for the
  375. * specified algorithm will be used. If an
  376. * invalid key size is used, GnuPG will do its
  377. * best to round it to a valid size.
  378. * @param integer $usage optional. A bitwise combination of key usages.
  379. * If not specified, the sub-key will be used
  380. * only to encrypt. This is the default behavior
  381. * of GnuPG in interactive mode. Use the
  382. * Crypt_GPG_SubKey::USAGE_* constants here.
  383. *
  384. * @return Crypt_GPG_KeyGenerator the current object, for fluent interface.
  385. */
  386. public function setSubKeyParams($algorithm, $size = '', $usage = 0)
  387. {
  388. $algorithm = intval($algorithm);
  389. if ($size != 0) {
  390. $size = intval($size);
  391. }
  392. if ($usage != 0) {
  393. $usage = intval($usage);
  394. }
  395. $usageSign = Crypt_GPG_SubKey::USAGE_SIGN;
  396. if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC
  397. && ($usage & $usageSign) === $usageSign
  398. ) {
  399. throw new Crypt_GPG_InvalidKeyParamsException(
  400. 'The Elgamal algorithm is not capable of signing. Please ' .
  401. 'specify a different algorithm or do not include signing ' .
  402. 'as a usage for the sub-key.',
  403. 0,
  404. $algorithm,
  405. $size,
  406. $usage
  407. );
  408. }
  409. $usageEncrypt = Crypt_GPG_SubKey::USAGE_ENCRYPT;
  410. if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_DSA
  411. && ($usage & $usageEncrypt) === $usageEncrypt
  412. ) {
  413. throw new Crypt_GPG_InvalidKeyParamsException(
  414. 'The DSA algorithm is not capable of encrypting. Please ' .
  415. 'specify a different algorithm or do not include encryption ' .
  416. 'as a usage for the sub-key.',
  417. 0,
  418. $algorithm,
  419. $size,
  420. $usage
  421. );
  422. }
  423. $this->subKeyAlgorithm = $algorithm;
  424. if ($size != 0) {
  425. $this->subKeySize = $size;
  426. }
  427. if ($usage != 0) {
  428. $this->subKeyUsage = $usage;
  429. }
  430. return $this;
  431. }
  432. // }}}
  433. // {{{ generateKey()
  434. /**
  435. * Generates a new key-pair in the current keyring
  436. *
  437. * Secure key generation requires true random numbers, and as such can be
  438. * solw. If the operating system runs out of entropy, key generation will
  439. * block until more entropy is available.
  440. *
  441. * If quick key generation is important, a hardware entropy generator, or
  442. * an entropy gathering daemon may be installed. For example,
  443. * administrators of Debian systems may want to install the 'randomsound'
  444. * package.
  445. *
  446. * @param string|Crypt_GPG_UserId $name either a {@link Crypt_GPG_UserId}
  447. * object, or a string containing
  448. * the name of the user id.
  449. * @param string $email optional. If <i>$name</i> is
  450. * specified as a string, this is
  451. * the email address of the user id.
  452. * @param string $comment optional. If <i>$name</i> is
  453. * specified as a string, this is
  454. * the comment of the user id.
  455. *
  456. * @return Crypt_GPG_Key the newly generated key.
  457. *
  458. * @throws Crypt_GPG_KeyNotCreatedException if the key parameters are
  459. * incorrect, if an unknown error occurs during key generation, or
  460. * if the newly generated key is not found in the keyring.
  461. *
  462. * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
  463. * Use the <kbd>debug</kbd> option and file a bug report if these
  464. * exceptions occur.
  465. */
  466. public function generateKey($name, $email = '', $comment = '')
  467. {
  468. $handle = uniqid('key', true);
  469. $userId = $this->getUserId($name, $email, $comment);
  470. $keyParams = array(
  471. 'Key-Type' => $this->keyAlgorithm,
  472. 'Key-Length' => $this->keySize,
  473. 'Key-Usage' => $this->getUsage($this->keyUsage),
  474. 'Subkey-Type' => $this->subKeyAlgorithm,
  475. 'Subkey-Length' => $this->subKeySize,
  476. 'Subkey-Usage' => $this->getUsage($this->subKeyUsage),
  477. 'Name-Real' => $userId->getName(),
  478. 'Handle' => $handle,
  479. );
  480. if ($this->expirationDate != 0) {
  481. // GnuPG only accepts granularity of days
  482. $expirationDate = date('Y-m-d', $this->expirationDate);
  483. $keyParams['Expire-Date'] = $expirationDate;
  484. }
  485. if (strlen($this->passphrase)) {
  486. $keyParams['Passphrase'] = $this->passphrase;
  487. }
  488. if ($userId->getEmail() != '') {
  489. $keyParams['Name-Email'] = $userId->getEmail();
  490. }
  491. if ($userId->getComment() != '') {
  492. $keyParams['Name-Comment'] = $userId->getComment();
  493. }
  494. $keyParamsFormatted = array();
  495. foreach ($keyParams as $name => $value) {
  496. $keyParamsFormatted[] = $name . ': ' . $value;
  497. }
  498. // This is required in GnuPG 2.1
  499. if (!strlen($this->passphrase)) {
  500. $keyParamsFormatted[] = '%no-protection';
  501. }
  502. $input = implode("\n", $keyParamsFormatted) . "\n%commit\n";
  503. $this->engine->reset();
  504. $this->engine->setProcessData('Handle', $handle);
  505. $this->engine->setInput($input);
  506. $this->engine->setOutput($output);
  507. $this->engine->setOperation('--gen-key', array('--batch'));
  508. try {
  509. $this->engine->run();
  510. } catch (Crypt_GPG_InvalidKeyParamsException $e) {
  511. switch ($this->engine->getProcessData('LineNumber')) {
  512. case 1:
  513. throw new Crypt_GPG_InvalidKeyParamsException(
  514. 'Invalid primary key algorithm specified.',
  515. 0,
  516. $this->keyAlgorithm,
  517. $this->keySize,
  518. $this->keyUsage
  519. );
  520. case 4:
  521. throw new Crypt_GPG_InvalidKeyParamsException(
  522. 'Invalid sub-key algorithm specified.',
  523. 0,
  524. $this->subKeyAlgorithm,
  525. $this->subKeySize,
  526. $this->subKeyUsage
  527. );
  528. default:
  529. throw $e;
  530. }
  531. }
  532. $fingerprint = $this->engine->getProcessData('KeyCreated');
  533. $keys = $this->_getKeys($fingerprint);
  534. if (count($keys) === 0) {
  535. throw new Crypt_GPG_KeyNotCreatedException(
  536. sprintf(
  537. 'Newly created key "%s" not found in keyring.',
  538. $fingerprint
  539. )
  540. );
  541. }
  542. return $keys[0];
  543. }
  544. // }}}
  545. // {{{ getUsage()
  546. /**
  547. * Builds a GnuPG key usage string suitable for key generation
  548. *
  549. * See <b>doc/DETAILS</b> in the
  550. * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
  551. * information on the key usage format.
  552. *
  553. * @param integer $usage a bitwise combination of the key usages. This is
  554. * a combination of the Crypt_GPG_SubKey::USAGE_*
  555. * constants.
  556. *
  557. * @return string the key usage string.
  558. */
  559. protected function getUsage($usage)
  560. {
  561. $map = array(
  562. Crypt_GPG_SubKey::USAGE_ENCRYPT => 'encrypt',
  563. Crypt_GPG_SubKey::USAGE_SIGN => 'sign',
  564. Crypt_GPG_SubKey::USAGE_CERTIFY => 'cert',
  565. Crypt_GPG_SubKey::USAGE_AUTHENTICATION => 'auth',
  566. );
  567. // cert is always used for primary keys and does not need to be
  568. // specified
  569. $usage &= ~Crypt_GPG_SubKey::USAGE_CERTIFY;
  570. $usageArray = array();
  571. foreach ($map as $key => $value) {
  572. if (($usage & $key) === $key) {
  573. $usageArray[] = $value;
  574. }
  575. }
  576. return implode(',', $usageArray);
  577. }
  578. // }}}
  579. // {{{ getUserId()
  580. /**
  581. * Gets a user id object from parameters
  582. *
  583. * @param string|Crypt_GPG_UserId $name either a {@link Crypt_GPG_UserId}
  584. * object, or a string containing
  585. * the name of the user id.
  586. * @param string $email optional. If <i>$name</i> is
  587. * specified as a string, this is
  588. * the email address of the user id.
  589. * @param string $comment optional. If <i>$name</i> is
  590. * specified as a string, this is
  591. * the comment of the user id.
  592. *
  593. * @return Crypt_GPG_UserId a user id object for the specified parameters.
  594. */
  595. protected function getUserId($name, $email = '', $comment = '')
  596. {
  597. if ($name instanceof Crypt_GPG_UserId) {
  598. $userId = $name;
  599. } else {
  600. $userId = new Crypt_GPG_UserId();
  601. $userId->setName($name)->setEmail($email)->setComment($comment);
  602. }
  603. return $userId;
  604. }
  605. // }}}
  606. }
  607. // }}}
  608. ?>