1<?php
2
3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5/**
6 * Crypt_GPG is a package to use GPG from PHP
7 *
8 * This package provides an object oriented interface to GNU Privacy
9 * Guard (GPG). It requires the GPG executable to be on the system.
10 *
11 * Though GPG can support symmetric-key cryptography, this package is intended
12 * only to facilitate public-key cryptography.
13 *
14 * This file contains the main GPG class. The class in this file lets you
15 * encrypt, decrypt, sign and verify data; import and delete keys; and perform
16 * other useful GPG tasks.
17 *
18 * Example usage:
19 * <code>
20 * <?php
21 * // encrypt some data
22 * $gpg = new Crypt_GPG();
23 * $gpg->addEncryptKey($mySecretKeyId);
24 * $encryptedData = $gpg->encrypt($data);
25 * ?>
26 * </code>
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, see
42 * <http://www.gnu.org/licenses/>
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-2013 silverorange
49 * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
50 * @link      http://pear.php.net/package/Crypt_GPG
51 * @link      http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
52 * @link      http://www.gnupg.org/
53 */
54
55/**
56 * Base class for GPG methods
57 */
58require_once 'Crypt/GPGAbstract.php';
59
60/**
61 * GPG exception classes.
62 */
63require_once 'Crypt/GPG/Exceptions.php';
64
65/**
66 * A class to use GPG from PHP
67 *
68 * This class provides an object oriented interface to GNU Privacy Guard (GPG).
69 *
70 * Though GPG can support symmetric-key cryptography, this class is intended
71 * only to facilitate public-key cryptography.
72 *
73 * @category  Encryption
74 * @package   Crypt_GPG
75 * @author    Nathan Fredrickson <nathan@silverorange.com>
76 * @author    Michael Gauthier <mike@silverorange.com>
77 * @copyright 2005-2013 silverorange
78 * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
79 * @link      http://pear.php.net/package/Crypt_GPG
80 * @link      http://www.gnupg.org/
81 */
82class Crypt_GPG extends Crypt_GPGAbstract
83{
84    /**
85     * Signing mode for normal signing of data. The signed message will not
86     * be readable without special software.
87     *
88     * This is the default signing mode.
89     *
90     * @see Crypt_GPG::sign()
91     * @see Crypt_GPG::signFile()
92     */
93    const SIGN_MODE_NORMAL = 1;
94
95    /**
96     * Signing mode for clearsigning data. Clearsigned signatures are ASCII
97     * armored data and are readable without special software. If the signed
98     * message is unencrypted, the message will still be readable. The message
99     * text will be in the original encoding.
100     *
101     * @see Crypt_GPG::sign()
102     * @see Crypt_GPG::signFile()
103     */
104    const SIGN_MODE_CLEAR = 2;
105
106    /**
107     * Signing mode for creating a detached signature. When using detached
108     * signatures, only the signature data is returned. The original message
109     * text may be distributed separately from the signature data. This is
110     * useful for miltipart/signed email messages as per
111     * {@link http://www.ietf.org/rfc/rfc3156.txt RFC 3156}.
112     *
113     * @see Crypt_GPG::sign()
114     * @see Crypt_GPG::signFile()
115     */
116    const SIGN_MODE_DETACHED = 3;
117
118    /**
119     * No formatting is performed.
120     *
121     * Example: C3BC615AD9C766E5A85C1F2716D27458B1BBA1C4
122     *
123     * @see Crypt_GPG::getFingerprint()
124     */
125    const FORMAT_NONE = 1;
126
127    /**
128     * Fingerprint is formatted in the format used by the GnuPG gpg command's
129     * default output.
130     *
131     * Example: C3BC 615A D9C7 66E5 A85C  1F27 16D2 7458 B1BB A1C4
132     *
133     * @see Crypt_GPG::getFingerprint()
134     */
135    const FORMAT_CANONICAL = 2;
136
137    /**
138     * Fingerprint is formatted in the format used when displaying X.509
139     * certificates
140     *
141     * Example: C3:BC:61:5A:D9:C7:66:E5:A8:5C:1F:27:16:D2:74:58:B1:BB:A1:C4
142     *
143     * @see Crypt_GPG::getFingerprint()
144     */
145    const FORMAT_X509 = 3;
146
147    /**
148     * Use to specify ASCII armored mode for returned data
149     */
150    const ARMOR_ASCII = true;
151
152    /**
153     * Use to specify binary mode for returned data
154     */
155    const ARMOR_BINARY = false;
156
157    /**
158     * Use to specify that line breaks in signed text should be normalized
159     */
160    const TEXT_NORMALIZED = true;
161
162    /**
163     * Use to specify that line breaks in signed text should not be normalized
164     */
165    const TEXT_RAW = false;
166
167    /**
168     * Keys used to encrypt
169     *
170     * The array is of the form:
171     * <code>
172     * array(
173     *   $key_id => array(
174     *     'fingerprint' => $fingerprint,
175     *     'passphrase'  => null
176     *   )
177     * );
178     * </code>
179     *
180     * @var array
181     * @see Crypt_GPG::addEncryptKey()
182     * @see Crypt_GPG::clearEncryptKeys()
183     */
184    protected $encryptKeys = array();
185
186    /**
187     * Keys used to decrypt
188     *
189     * The array is of the form:
190     * <code>
191     * array(
192     *   $key_id => array(
193     *     'fingerprint' => $fingerprint,
194     *     'passphrase'  => $passphrase
195     *   )
196     * );
197     * </code>
198     *
199     * @var array
200     * @see Crypt_GPG::addSignKey()
201     * @see Crypt_GPG::clearSignKeys()
202     */
203    protected $signKeys = array();
204
205    /**
206     * Keys used to sign
207     *
208     * The array is of the form:
209     * <code>
210     * array(
211     *   $key_id => array(
212     *     'fingerprint' => $fingerprint,
213     *     'passphrase'  => $passphrase
214     *   )
215     * );
216     * </code>
217     *
218     * @var array
219     * @see Crypt_GPG::addDecryptKey()
220     * @see Crypt_GPG::clearDecryptKeys()
221     */
222    protected $decryptKeys = array();
223
224    /**
225     * Passphrases used on import/export of private keys in GnuPG 2.1
226     *
227     * The array is of the form:
228     * <code>
229     * array($key_id => $passphrase);
230     * </code>
231     *
232     * @var array
233     * @see Crypt_GPG::addPassphrase()
234     * @see Crypt_GPG::clearPassphrases()
235     */
236    protected $passphrases = array();
237
238    /**
239     * Imports a public or private key into the keyring
240     *
241     * Keys may be removed from the keyring using
242     * {@link Crypt_GPG::deletePublicKey()} or
243     * {@link Crypt_GPG::deletePrivateKey()}.
244     *
245     * @param string $data the key data to be imported.
246     *
247     * @return array an associative array containing the following elements:
248     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
249     *                                                imported key,
250     *               - <kbd>public_imported</kbd>   - the number of public
251     *                                                keys imported,
252     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
253     *                                                public keys,
254     *               - <kbd>private_imported</kbd>  - the number of private
255     *                                                keys imported,
256     *               - <kbd>private_unchanged</kbd> - the number of unchanged
257     *                                                private keys.
258     *
259     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
260     *         data is is not valid key data.
261     *
262     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
263     *         incorrect or if a required passphrase is not specified. See
264     *         {@link Crypt_GPG::addPassphrase()}.
265     *
266     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
267     *         Use the <kbd>debug</kbd> option and file a bug report if these
268     *         exceptions occur.
269     *
270     * @see Crypt_GPG::addPassphrase()
271     * @see Crypt_GPG::clearPassphrases()
272     */
273    public function importKey($data)
274    {
275        return $this->_importKey($data, false);
276    }
277
278    /**
279     * Imports a public or private key file into the keyring
280     *
281     * Keys may be removed from the keyring using
282     * {@link Crypt_GPG::deletePublicKey()} or
283     * {@link Crypt_GPG::deletePrivateKey()}.
284     *
285     * @param string $filename the key file to be imported.
286     *
287     * @return array an associative array containing the following elements:
288     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
289     *                                                imported key,
290     *               - <kbd>public_imported</kbd>   - the number of public
291     *                                                keys imported,
292     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
293     *                                                public keys,
294     *               - <kbd>private_imported</kbd>  - the number of private
295     *                                                keys imported,
296     *               - <kbd>private_unchanged</kbd> - the number of unchanged
297     *                                                private keys.
298     *                                                  private keys.
299     *
300     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
301     *         data is is not valid key data.
302     *
303     * @throws Crypt_GPG_FileException if the key file is not readable.
304     *
305     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
306     *         incorrect or if a required passphrase is not specified. See
307     *         {@link Crypt_GPG::addPassphrase()}.
308     *
309     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
310     *         Use the <kbd>debug</kbd> option and file a bug report if these
311     *         exceptions occur.
312     */
313    public function importKeyFile($filename)
314    {
315        return $this->_importKey($filename, true);
316    }
317
318    /**
319     * Exports a private key from the keyring
320     *
321     * The exported key remains on the keyring. To delete the key, use
322     * {@link Crypt_GPG::deletePrivateKey()}.
323     *
324     * If more than one key fingerprint is available for the specified
325     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
326     * first private key is exported.
327     *
328     * @param string  $keyId either the full uid of the private key, the email
329     *                       part of the uid of the private key or the key id of
330     *                       the private key. For example,
331     *                       "Test User (example) <test@example.com>",
332     *                       "test@example.com" or a hexadecimal string.
333     * @param boolean $armor optional. If true, ASCII armored data is returned;
334     *                       otherwise, binary data is returned. Defaults to
335     *                       true.
336     *
337     * @return string the private key data.
338     *
339     * @throws Crypt_GPG_KeyNotFoundException if a private key with the given
340     *         <kbd>$keyId</kbd> is not found.
341     *
342     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
343     *         incorrect or if a required passphrase is not specified. See
344     *         {@link Crypt_GPG::addPassphrase()}.
345     *
346     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
347     *         Use the <kbd>debug</kbd> option and file a bug report if these
348     *         exceptions occur.
349     */
350    public function exportPrivateKey($keyId, $armor = true)
351    {
352        return $this->_exportKey($keyId, $armor, true);
353    }
354
355    /**
356     * Exports a public key from the keyring
357     *
358     * The exported key remains on the keyring. To delete the public key, use
359     * {@link Crypt_GPG::deletePublicKey()}.
360     *
361     * If more than one key fingerprint is available for the specified
362     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
363     * first public key is exported.
364     *
365     * @param string  $keyId either the full uid of the public key, the email
366     *                       part of the uid of the public key or the key id of
367     *                       the public key. For example,
368     *                       "Test User (example) <test@example.com>",
369     *                       "test@example.com" or a hexadecimal string.
370     * @param boolean $armor optional. If true, ASCII armored data is returned;
371     *                       otherwise, binary data is returned. Defaults to
372     *                       true.
373     *
374     * @return string the public key data.
375     *
376     * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
377     *         <kbd>$keyId</kbd> is not found.
378     *
379     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
380     *         Use the <kbd>debug</kbd> option and file a bug report if these
381     *         exceptions occur.
382     */
383    public function exportPublicKey($keyId, $armor = true)
384    {
385        return $this->_exportKey($keyId, $armor, false);
386    }
387
388    /**
389     * Deletes a public key from the keyring
390     *
391     * If more than one key fingerprint is available for the specified
392     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
393     * first public key is deleted.
394     *
395     * The private key must be deleted first or an exception will be thrown.
396     * In GnuPG >= 2.1 this limitation does not exist.
397     * See {@link Crypt_GPG::deletePrivateKey()}.
398     *
399     * @param string $keyId either the full uid of the public key, the email
400     *                      part of the uid of the public key or the key id of
401     *                      the public key. For example,
402     *                      "Test User (example) <test@example.com>",
403     *                      "test@example.com" or a hexadecimal string.
404     *
405     * @return void
406     *
407     * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
408     *         <kbd>$keyId</kbd> is not found.
409     *
410     * @throws Crypt_GPG_DeletePrivateKeyException if the specified public key
411     *         has an associated private key on the keyring. The private key
412     *         must be deleted first (when using GnuPG < 2.1).
413     *
414     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
415     *         Use the <kbd>debug</kbd> option and file a bug report if these
416     *         exceptions occur.
417     */
418    public function deletePublicKey($keyId)
419    {
420        $fingerprint = $this->getFingerprint($keyId);
421
422        if ($fingerprint === null) {
423            throw new Crypt_GPG_KeyNotFoundException(
424                'Public key not found: ' . $keyId,
425                self::ERROR_KEY_NOT_FOUND,
426                $keyId
427            );
428        }
429
430        $operation = '--delete-key ' . escapeshellarg($fingerprint);
431        $arguments = array(
432            '--batch',
433            '--yes'
434        );
435
436        $this->engine->reset();
437        $this->engine->setOperation($operation, $arguments);
438        $this->engine->run();
439    }
440
441    /**
442     * Deletes a private key from the keyring
443     *
444     * If more than one key fingerprint is available for the specified
445     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
446     * first private key is deleted.
447     *
448     * Calls GPG with the <kbd>--delete-secret-key</kbd> command.
449     *
450     * @param string $keyId either the full uid of the private key, the email
451     *                      part of the uid of the private key or the key id of
452     *                      the private key. For example,
453     *                      "Test User (example) <test@example.com>",
454     *                      "test@example.com" or a hexadecimal string.
455     *
456     * @return void
457     *
458     * @throws Crypt_GPG_KeyNotFoundException if a private key with the given
459     *         <kbd>$keyId</kbd> is not found.
460     *
461     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
462     *         Use the <kbd>debug</kbd> option and file a bug report if these
463     *         exceptions occur.
464     */
465    public function deletePrivateKey($keyId)
466    {
467        $fingerprint = $this->getFingerprint($keyId);
468
469        if ($fingerprint === null) {
470            throw new Crypt_GPG_KeyNotFoundException(
471                'Private key not found: ' . $keyId,
472                self::ERROR_KEY_NOT_FOUND,
473                $keyId
474            );
475        }
476
477        $operation = '--delete-secret-key ' . escapeshellarg($fingerprint);
478        $arguments = array(
479            '--batch',
480            '--yes'
481        );
482
483        $this->engine->reset();
484        $this->engine->setOperation($operation, $arguments);
485        $this->engine->run();
486    }
487
488    /**
489     * Gets the available keys in the keyring
490     *
491     * Calls GPG with the <kbd>--list-keys</kbd> command and grabs keys. See
492     * the first section of <b>doc/DETAILS</b> in the
493     * {@link http://www.gnupg.org/download/ GPG package} for a detailed
494     * description of how the GPG command output is parsed.
495     *
496     * @param string $keyId optional. Only keys with that match the specified
497     *                      pattern are returned. The pattern may be part of
498     *                      a user id, a key id or a key fingerprint. If not
499     *                      specified, all keys are returned.
500     *
501     * @return array an array of {@link Crypt_GPG_Key} objects. If no keys
502     *               match the specified <kbd>$keyId</kbd> an empty array is
503     *               returned.
504     *
505     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
506     *         Use the <kbd>debug</kbd> option and file a bug report if these
507     *         exceptions occur.
508     *
509     * @see Crypt_GPG_Key
510     */
511    public function getKeys($keyId = '')
512    {
513        return parent::_getKeys($keyId);
514    }
515
516    /**
517     * Gets a key fingerprint from the keyring
518     *
519     * If more than one key fingerprint is available (for example, if you use
520     * a non-unique user id) only the first key fingerprint is returned.
521     *
522     * Calls the GPG <kbd>--list-keys</kbd> command with the
523     * <kbd>--with-fingerprint</kbd> option to retrieve a public key
524     * fingerprint.
525     *
526     * @param string  $keyId  either the full user id of the key, the email
527     *                        part of the user id of the key, or the key id of
528     *                        the key. For example,
529     *                        "Test User (example) <test@example.com>",
530     *                        "test@example.com" or a hexadecimal string.
531     * @param integer $format optional. How the fingerprint should be formatted.
532     *                        Use {@link Crypt_GPG::FORMAT_X509} for X.509
533     *                        certificate format,
534     *                        {@link Crypt_GPG::FORMAT_CANONICAL} for the format
535     *                        used by GnuPG output and
536     *                        {@link Crypt_GPG::FORMAT_NONE} for no formatting.
537     *                        Defaults to <code>Crypt_GPG::FORMAT_NONE</code>.
538     *
539     * @return string the fingerprint of the key, or null if no fingerprint
540     *                is found for the given <kbd>$keyId</kbd>.
541     *
542     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
543     *         Use the <kbd>debug</kbd> option and file a bug report if these
544     *         exceptions occur.
545     */
546    public function getFingerprint($keyId, $format = self::FORMAT_NONE)
547    {
548        $output    = '';
549        $operation = '--list-keys ' . escapeshellarg($keyId);
550        $arguments = array(
551            '--with-colons',
552            '--with-fingerprint'
553        );
554
555        $this->engine->reset();
556        $this->engine->setOutput($output);
557        $this->engine->setOperation($operation, $arguments);
558        $this->engine->run();
559
560        $fingerprint = null;
561
562        foreach (explode(PHP_EOL, $output) as $line) {
563            if (mb_substr($line, 0, 3, '8bit') == 'fpr') {
564                $lineExp     = explode(':', $line);
565                $fingerprint = $lineExp[9];
566
567                switch ($format) {
568                case self::FORMAT_CANONICAL:
569                    $fingerprintExp = str_split($fingerprint, 4);
570                    $format         = '%s %s %s %s %s  %s %s %s %s %s';
571                    $fingerprint    = vsprintf($format, $fingerprintExp);
572                    break;
573
574                case self::FORMAT_X509:
575                    $fingerprintExp = str_split($fingerprint, 2);
576                    $fingerprint    = implode(':', $fingerprintExp);
577                    break;
578                }
579
580                break;
581            }
582        }
583
584        return $fingerprint;
585    }
586
587    /**
588     * Get information about the last signature that was created.
589     *
590     * @return Crypt_GPG_SignatureCreationInfo
591     */
592    public function getLastSignatureInfo()
593    {
594        return $this->engine->getProcessData('SignatureInfo');
595    }
596
597    /**
598     * Encrypts string data
599     *
600     * Data is ASCII armored by default but may optionally be returned as
601     * binary.
602     *
603     * @param string  $data  the data to be encrypted.
604     * @param boolean $armor optional. If true, ASCII armored data is returned;
605     *                       otherwise, binary data is returned. Defaults to
606     *                       true.
607     *
608     * @return string the encrypted data.
609     *
610     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
611     *         See {@link Crypt_GPG::addEncryptKey()}.
612     *
613     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
614     *         Use the <kbd>debug</kbd> option and file a bug report if these
615     *         exceptions occur.
616     *
617     * @sensitive $data
618     */
619    public function encrypt($data, $armor = self::ARMOR_ASCII)
620    {
621        return $this->_encrypt($data, false, null, $armor);
622    }
623
624    /**
625     * Encrypts a file
626     *
627     * Encrypted data is ASCII armored by default but may optionally be saved
628     * as binary.
629     *
630     * @param string  $filename      the filename of the file to encrypt.
631     * @param string  $encryptedFile optional. The filename of the file in
632     *                               which to store the encrypted data. If null
633     *                               or unspecified, the encrypted data is
634     *                               returned as a string.
635     * @param boolean $armor         optional. If true, ASCII armored data is
636     *                               returned; otherwise, binary data is
637     *                               returned. Defaults to true.
638     *
639     * @return void|string if the <kbd>$encryptedFile</kbd> parameter is null,
640     *                     a string containing the encrypted data is returned.
641     *
642     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
643     *         See {@link Crypt_GPG::addEncryptKey()}.
644     *
645     * @throws Crypt_GPG_FileException if the output file is not writeable or
646     *         if the input file is not readable.
647     *
648     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
649     *         Use the <kbd>debug</kbd> option and file a bug report if these
650     *         exceptions occur.
651     */
652    public function encryptFile(
653        $filename,
654        $encryptedFile = null,
655        $armor = self::ARMOR_ASCII
656    ) {
657        return $this->_encrypt($filename, true, $encryptedFile, $armor);
658    }
659
660    /**
661     * Encrypts and signs data
662     *
663     * Data is encrypted and signed in a single pass.
664     *
665     * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
666     * encrypted-signed data without decrypting it at the same time. If you try
667     * to use {@link Crypt_GPG::verify()} method on encrypted-signed data with
668     * earlier GnuPG versions, you will get an error. Please use
669     * {@link Crypt_GPG::decryptAndVerify()} to verify encrypted-signed data.
670     *
671     * @param string  $data  the data to be encrypted and signed.
672     * @param boolean $armor optional. If true, ASCII armored data is returned;
673     *                       otherwise, binary data is returned. Defaults to
674     *                       true.
675     *
676     * @return string the encrypted signed data.
677     *
678     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
679     *         or if no signing key is specified. See
680     *         {@link Crypt_GPG::addEncryptKey()} and
681     *         {@link Crypt_GPG::addSignKey()}.
682     *
683     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
684     *         incorrect or if a required passphrase is not specified.
685     *
686     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
687     *         Use the <kbd>debug</kbd> option and file a bug report if these
688     *         exceptions occur.
689     *
690     * @see Crypt_GPG::decryptAndVerify()
691     */
692    public function encryptAndSign($data, $armor = self::ARMOR_ASCII)
693    {
694        return $this->_encryptAndSign($data, false, null, $armor);
695    }
696
697    /**
698     * Encrypts and signs a file
699     *
700     * The file is encrypted and signed in a single pass.
701     *
702     * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
703     * encrypted-signed files without decrypting them at the same time. If you
704     * try to use {@link Crypt_GPG::verify()} method on encrypted-signed files
705     * with earlier GnuPG versions, you will get an error. Please use
706     * {@link Crypt_GPG::decryptAndVerifyFile()} to verify encrypted-signed
707     * files.
708     *
709     * @param string  $filename   the name of the file containing the data to
710     *                            be encrypted and signed.
711     * @param string  $signedFile optional. The name of the file in which the
712     *                            encrypted, signed data should be stored. If
713     *                            null or unspecified, the encrypted, signed
714     *                            data is returned as a string.
715     * @param boolean $armor      optional. If true, ASCII armored data is
716     *                            returned; otherwise, binary data is returned.
717     *                            Defaults to true.
718     *
719     * @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
720     *                     string containing the encrypted, signed data is
721     *                     returned.
722     *
723     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
724     *         or if no signing key is specified. See
725     *         {@link Crypt_GPG::addEncryptKey()} and
726     *         {@link Crypt_GPG::addSignKey()}.
727     *
728     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
729     *         incorrect or if a required passphrase is not specified.
730     *
731     * @throws Crypt_GPG_FileException if the output file is not writeable or
732     *         if the input file is not readable.
733     *
734     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
735     *         Use the <kbd>debug</kbd> option and file a bug report if these
736     *         exceptions occur.
737     *
738     * @see Crypt_GPG::decryptAndVerifyFile()
739     */
740    public function encryptAndSignFile(
741        $filename,
742        $signedFile = null,
743        $armor = self::ARMOR_ASCII
744    ) {
745        return $this->_encryptAndSign($filename, true, $signedFile, $armor);
746    }
747
748    /**
749     * Decrypts string data
750     *
751     * This method assumes the required private key is available in the keyring
752     * and throws an exception if the private key is not available. To add a
753     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
754     * {@link Crypt_GPG::importKeyFile()} methods.
755     *
756     * @param string $encryptedData the data to be decrypted.
757     *
758     * @return string the decrypted data.
759     *
760     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
761     *         decrypt the data is not in the user's keyring.
762     *
763     * @throws Crypt_GPG_NoDataException if specified data does not contain
764     *         GPG encrypted data.
765     *
766     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
767     *         incorrect or if a required passphrase is not specified. See
768     *         {@link Crypt_GPG::addDecryptKey()}.
769     *
770     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
771     *         Use the <kbd>debug</kbd> option and file a bug report if these
772     *         exceptions occur.
773     */
774    public function decrypt($encryptedData)
775    {
776        return $this->_decrypt($encryptedData, false, null);
777    }
778
779    /**
780     * Decrypts a file
781     *
782     * This method assumes the required private key is available in the keyring
783     * and throws an exception if the private key is not available. To add a
784     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
785     * {@link Crypt_GPG::importKeyFile()} methods.
786     *
787     * @param string $encryptedFile the name of the encrypted file data to
788     *                              decrypt.
789     * @param string $decryptedFile optional. The name of the file to which the
790     *                              decrypted data should be written. If null
791     *                              or unspecified, the decrypted data is
792     *                              returned as a string.
793     *
794     * @return void|string if the <kbd>$decryptedFile</kbd> parameter is null,
795     *                     a string containing the decrypted data is returned.
796     *
797     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
798     *         decrypt the data is not in the user's keyring.
799     *
800     * @throws Crypt_GPG_NoDataException if specified data does not contain
801     *         GPG encrypted data.
802     *
803     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
804     *         incorrect or if a required passphrase is not specified. See
805     *         {@link Crypt_GPG::addDecryptKey()}.
806     *
807     * @throws Crypt_GPG_FileException if the output file is not writeable or
808     *         if the input file is not readable.
809     *
810     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
811     *         Use the <kbd>debug</kbd> option and file a bug report if these
812     *         exceptions occur.
813     */
814    public function decryptFile($encryptedFile, $decryptedFile = null)
815    {
816        return $this->_decrypt($encryptedFile, true, $decryptedFile);
817    }
818
819    /**
820     * Decrypts and verifies string data
821     *
822     * This method assumes the required private key is available in the keyring
823     * and throws an exception if the private key is not available. To add a
824     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
825     * {@link Crypt_GPG::importKeyFile()} methods.
826     *
827     * @param string  $encryptedData      the encrypted, signed data to be decrypted
828     *                                    and verified.
829     * @param boolean $ignoreVerifyErrors enables ignoring of signature
830     *                                    verification errors caused by missing public key
831     *                                    When enabled Crypt_GPG_KeyNotFoundException
832     *                                    will not be thrown.
833     *
834     * @return array two element array. The array has an element 'data'
835     *               containing the decrypted data and an element
836     *               'signatures' containing an array of
837     *               {@link Crypt_GPG_Signature} objects for the signed data.
838     *
839     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
840     *         decrypt the data or the public key to verify the signature
841     *         is not in the user's keyring.
842     *
843     * @throws Crypt_GPG_NoDataException if specified data does not contain
844     *         GPG encrypted data.
845     *
846     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
847     *         incorrect or if a required passphrase is not specified. See
848     *         {@link Crypt_GPG::addDecryptKey()}.
849     *
850     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
851     *         Use the <kbd>debug</kbd> option and file a bug report if these
852     *         exceptions occur.
853     */
854    public function decryptAndVerify($encryptedData, $ignoreVerifyErrors = false)
855    {
856        return $this->_decryptAndVerify($encryptedData, false, null, $ignoreVerifyErrors);
857    }
858
859    /**
860     * Decrypts and verifies a signed, encrypted file
861     *
862     * This method assumes the required private key is available in the keyring
863     * and throws an exception if the private key is not available. To add a
864     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
865     * {@link Crypt_GPG::importKeyFile()} methods.
866     *
867     * @param string  $encryptedFile      the name of the signed, encrypted file to
868     *                                    to decrypt and verify.
869     * @param string  $decryptedFile      optional. The name of the file to which the
870     *                                    decrypted data should be written. If null
871     *                                    or unspecified, the decrypted data is
872     *                                    returned in the results array.
873     * @param boolean $ignoreVerifyErrors enables ignoring of signature
874     *                                    verification errors caused by missing public key
875     *                                    When enabled Crypt_GPG_KeyNotFoundException
876     *                                    will not be thrown.
877     *
878     * @return array two element array. The array has an element 'data'
879     *               containing the decrypted data and an element
880     *               'signatures' containing an array of
881     *               {@link Crypt_GPG_Signature} objects for the signed data.
882     *               If the decrypted data is written to a file, the 'data'
883     *               element is null.
884     *
885     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
886     *         decrypt the data or the public key to verify the signature
887     *         is not in the user's keyring.
888     *
889     * @throws Crypt_GPG_NoDataException if specified data does not contain
890     *         GPG encrypted data.
891     *
892     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
893     *         incorrect or if a required passphrase is not specified. See
894     *         {@link Crypt_GPG::addDecryptKey()}.
895     *
896     * @throws Crypt_GPG_FileException if the output file is not writeable or
897     *         if the input file is not readable.
898     *
899     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
900     *         Use the <kbd>debug</kbd> option and file a bug report if these
901     *         exceptions occur.
902     */
903    public function decryptAndVerifyFile($encryptedFile, $decryptedFile = null, $ignoreVerifyErrors = false)
904    {
905        return $this->_decryptAndVerify($encryptedFile, true, $decryptedFile, $ignoreVerifyErrors);
906    }
907
908    /**
909     * Signs data
910     *
911     * Data may be signed using any one of the three available signing modes:
912     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
913     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
914     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
915     *
916     * @param string  $data     the data to be signed.
917     * @param int     $mode     optional. The data signing mode to use. Should
918     *                          be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
919     *                          {@link Crypt_GPG::SIGN_MODE_CLEAR} or
920     *                          {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
921     *                          specified, defaults to
922     *                          <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
923     * @param boolean $armor    optional. If true, ASCII armored data is
924     *                          returned; otherwise, binary data is returned.
925     *                          Defaults to true. This has no effect if the
926     *                          mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
927     *                          used.
928     * @param boolean $textmode optional. If true, line-breaks in signed data
929     *                          are normalized. Use this option when signing
930     *                          e-mail, or for greater compatibility between
931     *                          systems with different line-break formats.
932     *                          Defaults to false. This has no effect if the
933     *                          mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
934     *                          used as clear-signing always uses textmode.
935     *
936     * @return string the signed data, or the signature data if a detached
937     *                signature is requested.
938     *
939     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
940     *         See {@link Crypt_GPG::addSignKey()}.
941     *
942     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
943     *         incorrect or if a required passphrase is not specified.
944     *
945     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
946     *         Use the <kbd>debug</kbd> option and file a bug report if these
947     *         exceptions occur.
948     */
949    public function sign(
950        $data,
951        $mode = self::SIGN_MODE_NORMAL,
952        $armor = self::ARMOR_ASCII,
953        $textmode = self::TEXT_RAW
954    ) {
955        return $this->_sign($data, false, null, $mode, $armor, $textmode);
956    }
957
958    /**
959     * Signs a file
960     *
961     * The file may be signed using any one of the three available signing
962     * modes:
963     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
964     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
965     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
966     *
967     * @param string  $filename   the name of the file containing the data to
968     *                            be signed.
969     * @param string  $signedFile optional. The name of the file in which the
970     *                            signed data should be stored. If null or
971     *                            unspecified, the signed data is returned as a
972     *                            string.
973     * @param int     $mode       optional. The data signing mode to use. Should
974     *                            be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
975     *                            {@link Crypt_GPG::SIGN_MODE_CLEAR} or
976     *                            {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
977     *                            specified, defaults to
978     *                            <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
979     * @param boolean $armor      optional. If true, ASCII armored data is
980     *                            returned; otherwise, binary data is returned.
981     *                            Defaults to true. This has no effect if the
982     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
983     *                            used.
984     * @param boolean $textmode   optional. If true, line-breaks in signed data
985     *                            are normalized. Use this option when signing
986     *                            e-mail, or for greater compatibility between
987     *                            systems with different line-break formats.
988     *                            Defaults to false. This has no effect if the
989     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
990     *                            used as clear-signing always uses textmode.
991     *
992     * @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
993     *                     string containing the signed data (or the signature
994     *                     data if a detached signature is requested) is
995     *                     returned.
996     *
997     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
998     *         See {@link Crypt_GPG::addSignKey()}.
999     *
1000     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
1001     *         incorrect or if a required passphrase is not specified.
1002     *
1003     * @throws Crypt_GPG_FileException if the output file is not writeable or
1004     *         if the input file is not readable.
1005     *
1006     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1007     *         Use the <kbd>debug</kbd> option and file a bug report if these
1008     *         exceptions occur.
1009     */
1010    public function signFile(
1011        $filename,
1012        $signedFile = null,
1013        $mode = self::SIGN_MODE_NORMAL,
1014        $armor = self::ARMOR_ASCII,
1015        $textmode = self::TEXT_RAW
1016    ) {
1017        return $this->_sign(
1018            $filename,
1019            true,
1020            $signedFile,
1021            $mode,
1022            $armor,
1023            $textmode
1024        );
1025    }
1026
1027    /**
1028     * Verifies signed data
1029     *
1030     * The {@link Crypt_GPG::decrypt()} method may be used to get the original
1031     * message if the signed data is not clearsigned and does not use a
1032     * detached signature.
1033     *
1034     * @param string $signedData the signed data to be verified.
1035     * @param string $signature  optional. If verifying data signed using a
1036     *                           detached signature, this must be the detached
1037     *                           signature data. The data that was signed is
1038     *                           specified in <kbd>$signedData</kbd>.
1039     *
1040     * @return array an array of {@link Crypt_GPG_Signature} objects for the
1041     *               signed data. For each signature that is valid, the
1042     *               {@link Crypt_GPG_Signature::isValid()} will return true.
1043     *
1044     * @throws Crypt_GPG_KeyNotFoundException if the public key needed for
1045     *         signature verification is not in the user's keyring.
1046     *
1047     * @throws Crypt_GPG_NoDataException if the provided data is not signed
1048     *         data.
1049     *
1050     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1051     *         Use the <kbd>debug</kbd> option and file a bug report if these
1052     *         exceptions occur.
1053     *
1054     * @see Crypt_GPG_Signature
1055     */
1056    public function verify($signedData, $signature = '')
1057    {
1058        return $this->_verify($signedData, false, $signature);
1059    }
1060
1061    /**
1062     * Verifies a signed file
1063     *
1064     * The {@link Crypt_GPG::decryptFile()} method may be used to get the
1065     * original message if the signed data is not clearsigned and does not use
1066     * a detached signature.
1067     *
1068     * @param string $filename  the signed file to be verified.
1069     * @param string $signature optional. If verifying a file signed using a
1070     *                          detached signature, this must be the detached
1071     *                          signature data. The file that was signed is
1072     *                          specified in <kbd>$filename</kbd>.
1073     *
1074     * @return array an array of {@link Crypt_GPG_Signature} objects for the
1075     *               signed data. For each signature that is valid, the
1076     *               {@link Crypt_GPG_Signature::isValid()} will return true.
1077     *
1078     * @throws Crypt_GPG_KeyNotFoundException if the public key needed for
1079     *         signature verification is not in the user's keyring.
1080     *
1081     * @throws Crypt_GPG_NoDataException if the provided data is not signed
1082     *         data.
1083     *
1084     * @throws Crypt_GPG_FileException if the input file is not readable.
1085     *
1086     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1087     *         Use the <kbd>debug</kbd> option and file a bug report if these
1088     *         exceptions occur.
1089     *
1090     * @see Crypt_GPG_Signature
1091     */
1092    public function verifyFile($filename, $signature = '')
1093    {
1094        return $this->_verify($filename, true, $signature);
1095    }
1096
1097    /**
1098     * Adds a key to use for decryption
1099     *
1100     * @param mixed  $key        the key to use. This may be a key identifier,
1101     *                           user id, fingerprint, {@link Crypt_GPG_Key} or
1102     *                           {@link Crypt_GPG_SubKey}. The key must be able
1103     *                           to encrypt.
1104     * @param string $passphrase optional. The passphrase of the key required
1105     *                           for decryption.
1106     *
1107     * @return Crypt_GPG the current object, for fluent interface.
1108     *
1109     * @see Crypt_GPG::decrypt()
1110     * @see Crypt_GPG::decryptFile()
1111     * @see Crypt_GPG::clearDecryptKeys()
1112     * @see Crypt_GPG::_addKey()
1113     *
1114     * @sensitive $passphrase
1115     */
1116    public function addDecryptKey($key, $passphrase = null)
1117    {
1118        $this->_addKey($this->decryptKeys, false, false, $key, $passphrase);
1119        return $this;
1120    }
1121
1122    /**
1123     * Adds a key to use for encryption
1124     *
1125     * @param mixed $key the key to use. This may be a key identifier, user id
1126     *                   user id, fingerprint, {@link Crypt_GPG_Key} or
1127     *                   {@link Crypt_GPG_SubKey}. The key must be able to
1128     *                   encrypt.
1129     *
1130     * @return Crypt_GPG the current object, for fluent interface.
1131     *
1132     * @see Crypt_GPG::encrypt()
1133     * @see Crypt_GPG::encryptFile()
1134     * @see Crypt_GPG::clearEncryptKeys()
1135     * @see Crypt_GPG::_addKey()
1136     */
1137    public function addEncryptKey($key)
1138    {
1139        $this->_addKey($this->encryptKeys, true, false, $key);
1140        return $this;
1141    }
1142
1143    /**
1144     * Adds a key to use for signing
1145     *
1146     * @param mixed  $key        the key to use. This may be a key identifier,
1147     *                           user id, fingerprint, {@link Crypt_GPG_Key} or
1148     *                           {@link Crypt_GPG_SubKey}. The key must be able
1149     *                           to sign.
1150     * @param string $passphrase optional. The passphrase of the key required
1151     *                           for signing.
1152     *
1153     * @return Crypt_GPG the current object, for fluent interface.
1154     *
1155     * @see Crypt_GPG::sign()
1156     * @see Crypt_GPG::signFile()
1157     * @see Crypt_GPG::clearSignKeys()
1158     * @see Crypt_GPG::_addKey()
1159     *
1160     * @sensitive $passphrase
1161     */
1162    public function addSignKey($key, $passphrase = null)
1163    {
1164        $this->_addKey($this->signKeys, false, true, $key, $passphrase);
1165        return $this;
1166    }
1167
1168    /**
1169     * Register a private key passphrase for import/export (GnuPG 2.1)
1170     *
1171     * @param mixed  $key        The key to use. This must be a key identifier,
1172     *                           or fingerprint.
1173     * @param string $passphrase The passphrase of the key.
1174     *
1175     * @return Crypt_GPG the current object, for fluent interface.
1176     *
1177     * @see Crypt_GPG::clearPassphrases()
1178     * @see Crypt_GPG::importKey()
1179     * @see Crypt_GPG::exportKey()
1180     *
1181     * @sensitive $passphrase
1182     */
1183    public function addPassphrase($key, $passphrase)
1184    {
1185        $this->passphrases[$key] = $passphrase;
1186        return $this;
1187    }
1188
1189    /**
1190     * Clears all decryption keys
1191     *
1192     * @return Crypt_GPG the current object, for fluent interface.
1193     *
1194     * @see Crypt_GPG::decrypt()
1195     * @see Crypt_GPG::addDecryptKey()
1196     */
1197    public function clearDecryptKeys()
1198    {
1199        $this->decryptKeys = array();
1200        return $this;
1201    }
1202
1203    /**
1204     * Clears all encryption keys
1205     *
1206     * @return Crypt_GPG the current object, for fluent interface.
1207     *
1208     * @see Crypt_GPG::encrypt()
1209     * @see Crypt_GPG::addEncryptKey()
1210     */
1211    public function clearEncryptKeys()
1212    {
1213        $this->encryptKeys = array();
1214        return $this;
1215    }
1216
1217    /**
1218     * Clears all signing keys
1219     *
1220     * @return Crypt_GPG the current object, for fluent interface.
1221     *
1222     * @see Crypt_GPG::sign()
1223     * @see Crypt_GPG::addSignKey()
1224     */
1225    public function clearSignKeys()
1226    {
1227        $this->signKeys = array();
1228        return $this;
1229    }
1230
1231    /**
1232     * Clears all private key passphrases
1233     *
1234     * @return Crypt_GPG the current object, for fluent interface.
1235     *
1236     * @see Crypt_GPG::importKey()
1237     * @see Crypt_GPG::exportKey()
1238     * @see Crypt_GPG::addPassphrase()
1239     */
1240    public function clearPassphrases()
1241    {
1242        $this->passphrases = array();
1243        return $this;
1244    }
1245
1246    /**
1247     * Tell if there are encryption keys registered
1248     *
1249     * @return boolean True if the data shall be encrypted
1250     */
1251    public function hasEncryptKeys()
1252    {
1253        return count($this->encryptKeys) > 0;
1254    }
1255
1256    /**
1257     * Tell if there are signing keys registered
1258     *
1259     * @return boolean True if the data shall be signed
1260     */
1261    public function hasSignKeys()
1262    {
1263        return count($this->signKeys) > 0;
1264    }
1265
1266    /**
1267     * Get list of GnuPG warnings collected on last operation.
1268     *
1269     * @return array List of warning messages
1270     */
1271    public function getWarnings()
1272    {
1273        return $this->engine->getProcessData('Warnings');
1274    }
1275
1276    /**
1277     * Adds a key to one of the internal key arrays
1278     *
1279     * This handles resolving full key objects from the provided
1280     * <kbd>$key</kbd> value.
1281     *
1282     * @param &array  $array      the array to which the key should be added.
1283     * @param boolean $encrypt    whether or not the key must be able to
1284     *                            encrypt.
1285     * @param boolean $sign       whether or not the key must be able to sign.
1286     * @param mixed   $key        the key to add. This may be a key identifier,
1287     *                            user id, fingerprint, {@link Crypt_GPG_Key} or
1288     *                            {@link Crypt_GPG_SubKey}.
1289     * @param string  $passphrase optional. The passphrase associated with the
1290     *                            key.
1291     *
1292     * @return void
1293     *
1294     * @sensitive $passphrase
1295     */
1296    protected function _addKey(array &$array, $encrypt, $sign, $key,
1297        $passphrase = null
1298    ) {
1299        $subKeys = array();
1300
1301        if (is_scalar($key)) {
1302            $keys = $this->getKeys($key);
1303            if (count($keys) == 0) {
1304                throw new Crypt_GPG_KeyNotFoundException(
1305                    'Key not found: ' . $key,
1306                    self::ERROR_KEY_NOT_FOUND,
1307                    $key
1308                );
1309            }
1310            $key = $keys[0];
1311        }
1312
1313        if ($key instanceof Crypt_GPG_Key) {
1314            if ($encrypt && !$key->canEncrypt()) {
1315                throw new InvalidArgumentException(
1316                    'Key "' . $key . '" cannot encrypt.'
1317                );
1318            }
1319
1320            if ($sign && !$key->canSign()) {
1321                throw new InvalidArgumentException(
1322                    'Key "' . $key . '" cannot sign.'
1323                );
1324            }
1325
1326            foreach ($key->getSubKeys() as $subKey) {
1327                $canEncrypt = $subKey->canEncrypt();
1328                $canSign    = $subKey->canSign();
1329                if (($encrypt && $sign && $canEncrypt && $canSign)
1330                    || ($encrypt && !$sign && $canEncrypt)
1331                    || (!$encrypt && $sign && $canSign)
1332                    || (!$encrypt && !$sign)
1333                ) {
1334                    // We add all subkeys that meet the requirements because we
1335                    // were not told which subkey is required.
1336                    $subKeys[] = $subKey;
1337                }
1338            }
1339        } elseif ($key instanceof Crypt_GPG_SubKey) {
1340            $subKeys[] = $key;
1341        }
1342
1343        if (count($subKeys) === 0) {
1344            throw new InvalidArgumentException(
1345                'Key "' . $key . '" is not in a recognized format.'
1346            );
1347        }
1348
1349        foreach ($subKeys as $subKey) {
1350            if ($encrypt && !$subKey->canEncrypt()) {
1351                throw new InvalidArgumentException(
1352                    'Key "' . $key . '" cannot encrypt.'
1353                );
1354            }
1355
1356            if ($sign && !$subKey->canSign()) {
1357                throw new InvalidArgumentException(
1358                    'Key "' . $key . '" cannot sign.'
1359                );
1360            }
1361
1362            $array[$subKey->getId()] = array(
1363                'fingerprint' => $subKey->getFingerprint(),
1364                'passphrase'  => $passphrase
1365            );
1366        }
1367    }
1368
1369    /**
1370     * Imports a public or private key into the keyring
1371     *
1372     * @param string  $key    the key to be imported.
1373     * @param boolean $isFile whether or not the input is a filename.
1374     *
1375     * @return array an associative array containing the following elements:
1376     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
1377     *                                                imported key,
1378     *               - <kbd>public_imported</kbd>   - the number of public
1379     *                                                keys imported,
1380     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
1381     *                                                public keys,
1382     *               - <kbd>private_imported</kbd>  - the number of private
1383     *                                                keys imported,
1384     *               - <kbd>private_unchanged</kbd> - the number of unchanged
1385     *                                                private keys.
1386     *
1387     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
1388     *         data is is not valid key data.
1389     *
1390     * @throws Crypt_GPG_FileException if the key file is not readable.
1391     *
1392     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1393     *         incorrect or if a required passphrase is not specified. See
1394     *         {@link Crypt_GPG::addPassphrase()}.
1395     *
1396     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1397     *         Use the <kbd>debug</kbd> option and file a bug report if these
1398     *         exceptions occur.
1399     */
1400    protected function _importKey($key, $isFile)
1401    {
1402        $result    = array();
1403        $arguments = array();
1404        $input     = $this->_prepareInput($key, $isFile, false);
1405        $version   = $this->engine->getVersion();
1406
1407        if (version_compare($version, '1.0.5', 'ge')
1408            && version_compare($version, '1.0.7', 'lt')
1409        ) {
1410            $arguments[] = '--allow-secret-key-import';
1411        }
1412
1413        if (empty($this->passphrases)) {
1414            $arguments[] = '--batch';
1415        }
1416
1417        $this->engine->reset();
1418        $this->engine->setPins($this->passphrases);
1419        $this->engine->setOperation('--import', $arguments);
1420        $this->engine->setInput($input);
1421        $this->engine->run();
1422
1423        return $this->engine->getProcessData('Import');
1424    }
1425
1426    /**
1427     * Exports a private or public key from the keyring
1428     *
1429     * If more than one key fingerprint is available for the specified
1430     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
1431     * first key is exported.
1432     *
1433     * @param string  $keyId   either the full uid of the key, the email
1434     *                         part of the uid of the key or the key id.
1435     * @param boolean $armor   optional. If true, ASCII armored data is returned;
1436     *                         otherwise, binary data is returned. Defaults to
1437     *                         true.
1438     * @param boolean $private return private instead of public key
1439     *
1440     * @return string the key data.
1441     *
1442     * @throws Crypt_GPG_KeyNotFoundException if a key with the given
1443     *         <kbd>$keyId</kbd> is not found.
1444     *
1445     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1446     *         incorrect or if a required passphrase is not specified. See
1447     *         {@link Crypt_GPG::addPassphrase()}.
1448     *
1449     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1450     *         Use the <kbd>debug</kbd> option and file a bug report if these
1451     *         exceptions occur.
1452     */
1453    protected function _exportKey($keyId, $armor = true, $private = false)
1454    {
1455        $fingerprint = $this->getFingerprint($keyId);
1456
1457        if ($fingerprint === null) {
1458            throw new Crypt_GPG_KeyNotFoundException(
1459                'Key not found: ' . $keyId,
1460                self::ERROR_KEY_NOT_FOUND,
1461                $keyId
1462            );
1463        }
1464
1465        $keyData   = '';
1466        $operation = $private ? '--export-secret-keys' : '--export';
1467        $operation .= ' ' . escapeshellarg($fingerprint);
1468        $arguments = $armor ? array('--armor') : array();
1469
1470        $this->engine->reset();
1471        $this->engine->setPins($this->passphrases);
1472        $this->engine->setOutput($keyData);
1473        $this->engine->setOperation($operation, $arguments);
1474        $this->engine->run();
1475
1476        return $keyData;
1477    }
1478
1479    /**
1480     * Encrypts data
1481     *
1482     * @param string  $data       the data to encrypt.
1483     * @param boolean $isFile     whether or not the data is a filename.
1484     * @param string  $outputFile the filename of the file in which to store
1485     *                            the encrypted data. If null, the encrypted
1486     *                            data is returned as a string.
1487     * @param boolean $armor      if true, ASCII armored data is returned;
1488     *                            otherwise, binary data is returned.
1489     *
1490     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
1491     *                     string containing the encrypted data is returned.
1492     *
1493     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
1494     *         See {@link Crypt_GPG::addEncryptKey()}.
1495     *
1496     * @throws Crypt_GPG_FileException if the output file is not writeable or
1497     *         if the input file is not readable.
1498     *
1499     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1500     *         Use the <kbd>debug</kbd> option and file a bug report if these
1501     *         exceptions occur.
1502     */
1503    protected function _encrypt($data, $isFile, $outputFile, $armor)
1504    {
1505        if (!$this->hasEncryptKeys()) {
1506            throw new Crypt_GPG_KeyNotFoundException(
1507                'No encryption keys specified.'
1508            );
1509        }
1510
1511        $input     = $this->_prepareInput($data, $isFile);
1512        $output    = $this->_prepareOutput($outputFile, $input);
1513        $arguments = $armor ? array('--armor') : array();
1514
1515        foreach ($this->encryptKeys as $key) {
1516            $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
1517        }
1518
1519        $this->engine->reset();
1520        $this->engine->setInput($input);
1521        $this->engine->setOutput($output);
1522        $this->engine->setOperation('--encrypt', $arguments);
1523        $this->engine->run();
1524
1525        if ($outputFile === null) {
1526            return $output;
1527        }
1528    }
1529
1530    /**
1531     * Decrypts data
1532     *
1533     * @param string  $data       the data to be decrypted.
1534     * @param boolean $isFile     whether or not the data is a filename.
1535     * @param string  $outputFile the name of the file to which the decrypted
1536     *                            data should be written. If null, the decrypted
1537     *                            data is returned as a string.
1538     *
1539     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
1540     *                     string containing the decrypted data is returned.
1541     *
1542     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
1543     *         decrypt the data is not in the user's keyring.
1544     *
1545     * @throws Crypt_GPG_NoDataException if specified data does not contain
1546     *         GPG encrypted data.
1547     *
1548     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1549     *         incorrect or if a required passphrase is not specified. See
1550     *         {@link Crypt_GPG::addDecryptKey()}.
1551     *
1552     * @throws Crypt_GPG_FileException if the output file is not writeable or
1553     *         if the input file is not readable.
1554     *
1555     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1556     *         Use the <kbd>debug</kbd> option and file a bug report if these
1557     *         exceptions occur.
1558     */
1559    protected function _decrypt($data, $isFile, $outputFile)
1560    {
1561        $input  = $this->_prepareInput($data, $isFile, false);
1562        $output = $this->_prepareOutput($outputFile, $input);
1563
1564        $this->engine->reset();
1565        $this->engine->setPins($this->decryptKeys);
1566        $this->engine->setOperation('--decrypt --skip-verify');
1567        $this->engine->setInput($input);
1568        $this->engine->setOutput($output);
1569        $this->engine->run();
1570
1571        if ($outputFile === null) {
1572            return $output;
1573        }
1574    }
1575
1576    /**
1577     * Signs data
1578     *
1579     * @param string  $data       the data to be signed.
1580     * @param boolean $isFile     whether or not the data is a filename.
1581     * @param string  $outputFile the name of the file in which the signed data
1582     *                            should be stored. If null, the signed data is
1583     *                            returned as a string.
1584     * @param int     $mode       the data signing mode to use. Should be one of
1585     *                            {@link Crypt_GPG::SIGN_MODE_NORMAL},
1586     *                            {@link Crypt_GPG::SIGN_MODE_CLEAR} or
1587     *                            {@link Crypt_GPG::SIGN_MODE_DETACHED}.
1588     * @param boolean $armor      if true, ASCII armored data is returned;
1589     *                            otherwise, binary data is returned. This has
1590     *                            no effect if the mode
1591     *                            <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
1592     *                            used.
1593     * @param boolean $textmode   if true, line-breaks in signed data be
1594     *                            normalized. Use this option when signing
1595     *                            e-mail, or for greater compatibility between
1596     *                            systems with different line-break formats.
1597     *                            Defaults to false. This has no effect if the
1598     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
1599     *                            used as clear-signing always uses textmode.
1600     *
1601     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
1602     *                     string containing the signed data (or the signature
1603     *                     data if a detached signature is requested) is
1604     *                     returned.
1605     *
1606     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
1607     *         See {@link Crypt_GPG::addSignKey()}.
1608     *
1609     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
1610     *         incorrect or if a required passphrase is not specified.
1611     *
1612     * @throws Crypt_GPG_FileException if the output file is not writeable or
1613     *         if the input file is not readable.
1614     *
1615     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1616     *         Use the <kbd>debug</kbd> option and file a bug report if these
1617     *         exceptions occur.
1618     */
1619    protected function _sign($data, $isFile, $outputFile, $mode, $armor,
1620        $textmode
1621    ) {
1622        if (!$this->hasSignKeys()) {
1623            throw new Crypt_GPG_KeyNotFoundException(
1624                'No signing keys specified.'
1625            );
1626        }
1627
1628        $input  = $this->_prepareInput($data, $isFile);
1629        $output = $this->_prepareOutput($outputFile, $input);
1630
1631        switch ($mode) {
1632        case self::SIGN_MODE_DETACHED:
1633            $operation = '--detach-sign';
1634            break;
1635        case self::SIGN_MODE_CLEAR:
1636            $operation = '--clearsign';
1637            break;
1638        case self::SIGN_MODE_NORMAL:
1639        default:
1640            $operation = '--sign';
1641            break;
1642        }
1643
1644        $arguments = array();
1645
1646        if ($armor) {
1647            $arguments[] = '--armor';
1648        }
1649        if ($textmode) {
1650            $arguments[] = '--textmode';
1651        }
1652
1653        foreach ($this->signKeys as $key) {
1654            $arguments[] = '--local-user ' .
1655                escapeshellarg($key['fingerprint']);
1656        }
1657
1658        $this->engine->reset();
1659        $this->engine->setPins($this->signKeys);
1660        $this->engine->setInput($input);
1661        $this->engine->setOutput($output);
1662        $this->engine->setOperation($operation, $arguments);
1663        $this->engine->run();
1664
1665        if ($outputFile === null) {
1666            return $output;
1667        }
1668    }
1669
1670    /**
1671     * Encrypts and signs data
1672     *
1673     * @param string  $data       the data to be encrypted and signed.
1674     * @param boolean $isFile     whether or not the data is a filename.
1675     * @param string  $outputFile the name of the file in which the encrypted,
1676     *                            signed data should be stored. If null, the
1677     *                            encrypted, signed data is returned as a
1678     *                            string.
1679     * @param boolean $armor      if true, ASCII armored data is returned;
1680     *                            otherwise, binary data is returned.
1681     *
1682     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
1683     *                     string containing the encrypted, signed data is
1684     *                     returned.
1685     *
1686     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
1687     *         or if no signing key is specified. See
1688     *         {@link Crypt_GPG::addEncryptKey()} and
1689     *         {@link Crypt_GPG::addSignKey()}.
1690     *
1691     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
1692     *         incorrect or if a required passphrase is not specified.
1693     *
1694     * @throws Crypt_GPG_FileException if the output file is not writeable or
1695     *         if the input file is not readable.
1696     *
1697     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1698     *         Use the <kbd>debug</kbd> option and file a bug report if these
1699     *         exceptions occur.
1700     */
1701    protected function _encryptAndSign($data, $isFile, $outputFile, $armor)
1702    {
1703        if (!$this->hasSignKeys()) {
1704            throw new Crypt_GPG_KeyNotFoundException(
1705                'No signing keys specified.'
1706            );
1707        }
1708
1709        if (!$this->hasEncryptKeys()) {
1710            throw new Crypt_GPG_KeyNotFoundException(
1711                'No encryption keys specified.'
1712            );
1713        }
1714
1715        $input     = $this->_prepareInput($data, $isFile);
1716        $output    = $this->_prepareOutput($outputFile, $input);
1717        $arguments = $armor ? array('--armor') : array();
1718
1719        foreach ($this->signKeys as $key) {
1720            $arguments[] = '--local-user ' .
1721                escapeshellarg($key['fingerprint']);
1722        }
1723
1724        foreach ($this->encryptKeys as $key) {
1725            $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
1726        }
1727
1728        $this->engine->reset();
1729        $this->engine->setPins($this->signKeys);
1730        $this->engine->setInput($input);
1731        $this->engine->setOutput($output);
1732        $this->engine->setOperation('--encrypt --sign', $arguments);
1733        $this->engine->run();
1734
1735        if ($outputFile === null) {
1736            return $output;
1737        }
1738    }
1739
1740    /**
1741     * Verifies data
1742     *
1743     * @param string  $data      the signed data to be verified.
1744     * @param boolean $isFile    whether or not the data is a filename.
1745     * @param string  $signature if verifying a file signed using a detached
1746     *                           signature, this must be the detached signature
1747     *                           data. Otherwise, specify ''.
1748     *
1749     * @return array an array of {@link Crypt_GPG_Signature} objects for the
1750     *               signed data.
1751     *
1752     * @throws Crypt_GPG_KeyNotFoundException if the public key needed for
1753     *         signature verification is not in the user's keyring.
1754     *
1755     * @throws Crypt_GPG_NoDataException if the provided data is not signed
1756     *         data.
1757     *
1758     * @throws Crypt_GPG_FileException if the input file is not readable.
1759     *
1760     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1761     *         Use the <kbd>debug</kbd> option and file a bug report if these
1762     *         exceptions occur.
1763     *
1764     * @see Crypt_GPG_Signature
1765     */
1766    protected function _verify($data, $isFile, $signature)
1767    {
1768        if ($signature == '') {
1769            $operation = '--verify';
1770            $arguments = array();
1771        } else {
1772            // Signed data goes in FD_MESSAGE, detached signature data goes in
1773            // FD_INPUT.
1774            $operation = '--verify - "-&' . Crypt_GPG_Engine::FD_MESSAGE. '"';
1775            $arguments = array('--enable-special-filenames');
1776        }
1777
1778        $input = $this->_prepareInput($data, $isFile, false);
1779
1780        $this->engine->reset();
1781
1782        if ($signature == '') {
1783            // signed or clearsigned data
1784            $this->engine->setInput($input);
1785        } else {
1786            // detached signature
1787            $this->engine->setInput($signature);
1788            $this->engine->setMessage($input);
1789        }
1790
1791        $this->engine->setOperation($operation, $arguments);
1792        $this->engine->run();
1793
1794        return $this->engine->getProcessData('Signatures');
1795    }
1796
1797    /**
1798     * Decrypts and verifies encrypted, signed data
1799     *
1800     * @param string  $data               the encrypted signed data to be decrypted and
1801     *                                    verified.
1802     * @param boolean $isFile             whether or not the data is a filename.
1803     * @param string  $outputFile         the name of the file to which the decrypted
1804     *                                    data should be written. If null, the decrypted
1805     *                                    data is returned in the results array.
1806     * @param boolean $ignoreVerifyErrors enables ignoring of signature verification
1807     *                                    errors caused by missing public key.
1808     *                                    When enabled Crypt_GPG_KeyNotFoundException
1809     *                                    will not be thrown.
1810     *
1811     * @return array two element array. The array has an element 'data'
1812     *               containing the decrypted data and an element
1813     *               'signatures' containing an array of
1814     *               {@link Crypt_GPG_Signature} objects for the signed data.
1815     *               If the decrypted data is written to a file, the 'data'
1816     *               element is null.
1817     *
1818     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
1819     *         decrypt the data is not in the user's keyring or if the public
1820     *         key needed for verification is not in the user's keyring.
1821     *
1822     * @throws Crypt_GPG_NoDataException if specified data does not contain
1823     *         GPG signed, encrypted data.
1824     *
1825     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1826     *         incorrect or if a required passphrase is not specified. See
1827     *         {@link Crypt_GPG::addDecryptKey()}.
1828     *
1829     * @throws Crypt_GPG_FileException if the output file is not writeable or
1830     *         if the input file is not readable.
1831     *
1832     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1833     *         Use the <kbd>debug</kbd> option and file a bug report if these
1834     *         exceptions occur.
1835     *
1836     * @see Crypt_GPG_Signature
1837     */
1838    protected function _decryptAndVerify($data, $isFile, $outputFile, $ignoreVerifyErrors = false)
1839    {
1840        $input  = $this->_prepareInput($data, $isFile, false);
1841        $output = $this->_prepareOutput($outputFile, $input);
1842
1843        $this->engine->reset();
1844        $this->engine->setPins($this->decryptKeys);
1845        $this->engine->setInput($input);
1846        $this->engine->setOutput($output);
1847        $this->engine->setOperation('--decrypt');
1848        $this->engine->setProcessData('IgnoreVerifyErrors', $ignoreVerifyErrors);
1849        $this->engine->run();
1850
1851        $return = array(
1852            'data'       => null,
1853            'signatures' => $this->engine->getProcessData('Signatures')
1854        );
1855
1856        if ($outputFile === null) {
1857            $return['data'] = $output;
1858        }
1859
1860        return $return;
1861    }
1862
1863    /**
1864     * Prepares command input
1865     *
1866     * @param string  $data       the input data.
1867     * @param boolean $isFile     whether or not the input is a filename.
1868     * @param boolean $allowEmpty whether to check if the input is not empty.
1869     *
1870     * @throws Crypt_GPG_NoDataException if the key data is missing.
1871     * @throws Crypt_GPG_FileException if the file is not readable.
1872     *
1873     * @return string The command input
1874     */
1875    protected function _prepareInput($data, $isFile = false, $allowEmpty = true)
1876    {
1877        if ($isFile) {
1878            $input = @fopen($data, 'rb');
1879            if ($input === false) {
1880                throw new Crypt_GPG_FileException(
1881                    'Could not open input file "' . $data . '"',
1882                    0,
1883                    $data
1884                );
1885            }
1886        } else {
1887            $input = strval($data);
1888            if (!$allowEmpty && $input === '') {
1889                throw new Crypt_GPG_NoDataException(
1890                    'No valid input data found.',
1891                    self::ERROR_NO_DATA
1892                );
1893            }
1894        }
1895
1896        return $input;
1897    }
1898
1899    /**
1900     * Prepares command output
1901     *
1902     * @param string  $outputFile the name of the file in which the output
1903     *                            data should be stored. If null, the output
1904     *                            data is returned as a string.
1905     * @param boolean $input      the input resource, in case it would need
1906     *                            to be released (closed) on exception.
1907     *
1908     * @throws Crypt_GPG_FileException if the file is not writeable.
1909     *
1910     * @return string The command output
1911     */
1912    protected function _prepareOutput($outputFile, $input = null)
1913    {
1914        if ($outputFile === null) {
1915            $output = '';
1916        } else {
1917            $output = @fopen($outputFile, 'wb');
1918            if ($output === false) {
1919                if (is_resource($input)) {
1920                    fclose($input);
1921                }
1922                throw new Crypt_GPG_FileException(
1923                    'Could not open output file "' . $outputFile . '"',
1924                    0,
1925                    $outputFile
1926                );
1927            }
1928        }
1929
1930        return $output;
1931    }
1932}
1933