3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6
* Crypt_GPG is a package to use GPG from PHP
8
* This package provides an object oriented interface to GNU Privacy
9
* Guard (GPG). It requires the GPG executable to be on the system.
11
* Though GPG can support symmetric-key cryptography, this package is intended
12
* only to facilitate public-key cryptography.
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.
21
* // encrypt some data
22
* $gpg = new Crypt_GPG();
23
* $gpg->addEncryptKey($mySecretKeyId);
24
* $encryptedData = $gpg->encrypt($data);
32
* This library is free software; you can redistribute it and/or modify
33
* it under the terms of the GNU Lesser General Public License as
34
* published by the Free Software Foundation; either version 2.1 of the
35
* License, or (at your option) any later version.
37
* This library is distributed in the hope that it will be useful,
38
* but WITHOUT ANY WARRANTY; without even the implied warranty of
39
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40
* Lesser General Public License for more details.
42
* You should have received a copy of the GNU Lesser General Public
43
* License along with this library; if not, write to the Free Software
44
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
46
* @category Encryption
48
* @author Nathan Fredrickson <nathan@silverorange.com>
49
* @author Michael Gauthier <mike@silverorange.com>
50
* @copyright 2005-2010 silverorange
51
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
52
* @version CVS: $Id: GPG.php 295622 2010-03-01 04:34:56Z gauthierm $
53
* @link http://pear.php.net/package/Crypt_GPG
54
* @link http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
55
* @link http://www.gnupg.org/
59
* Signature handler class
61
require_once 'Crypt/GPG/VerifyStatusHandler.php';
64
* Decryption handler class
66
require_once 'Crypt/GPG/DecryptStatusHandler.php';
71
require_once 'Crypt/GPG/Key.php';
76
require_once 'Crypt/GPG/SubKey.php';
81
require_once 'Crypt/GPG/UserId.php';
84
* GPG process and I/O engine class
86
require_once 'Crypt/GPG/Engine.php';
89
* GPG exception classes
91
require_once 'Crypt/GPG/Exceptions.php';
93
// {{{ class Crypt_GPG
96
* A class to use GPG from PHP
98
* This class provides an object oriented interface to GNU Privacy Guard (GPG).
100
* Though GPG can support symmetric-key cryptography, this class is intended
101
* only to facilitate public-key cryptography.
103
* @category Encryption
105
* @author Nathan Fredrickson <nathan@silverorange.com>
106
* @author Michael Gauthier <mike@silverorange.com>
107
* @copyright 2005-2010 silverorange
108
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
109
* @link http://pear.php.net/package/Crypt_GPG
110
* @link http://www.gnupg.org/
114
// {{{ class error constants
117
* Error code returned when there is no error.
119
const ERROR_NONE = 0;
122
* Error code returned when an unknown or unhandled error occurs.
124
const ERROR_UNKNOWN = 1;
127
* Error code returned when a bad passphrase is used.
129
const ERROR_BAD_PASSPHRASE = 2;
132
* Error code returned when a required passphrase is missing.
134
const ERROR_MISSING_PASSPHRASE = 3;
137
* Error code returned when a key that is already in the keyring is
140
const ERROR_DUPLICATE_KEY = 4;
143
* Error code returned the required data is missing for an operation.
145
* This could be missing key data, missing encrypted data or missing
148
const ERROR_NO_DATA = 5;
151
* Error code returned when an unsigned key is used.
153
const ERROR_UNSIGNED_KEY = 6;
156
* Error code returned when a key that is not self-signed is used.
158
const ERROR_NOT_SELF_SIGNED = 7;
161
* Error code returned when a public or private key that is not in the
164
const ERROR_KEY_NOT_FOUND = 8;
167
* Error code returned when an attempt to delete public key having a
168
* private key is made.
170
const ERROR_DELETE_PRIVATE_KEY = 9;
173
* Error code returned when one or more bad signatures are detected.
175
const ERROR_BAD_SIGNATURE = 10;
178
// {{{ class constants for data signing modes
181
* Signing mode for normal signing of data. The signed message will not
182
* be readable without special software.
184
* This is the default signing mode.
186
* @see Crypt_GPG::sign()
187
* @see Crypt_GPG::signFile()
189
const SIGN_MODE_NORMAL = 1;
192
* Signing mode for clearsigning data. Clearsigned signatures are ASCII
193
* armored data and are readable without special software. If the signed
194
* message is unencrypted, the message will still be readable. The message
195
* text will be in the original encoding.
197
* @see Crypt_GPG::sign()
198
* @see Crypt_GPG::signFile()
200
const SIGN_MODE_CLEAR = 2;
203
* Signing mode for creating a detached signature. When using detached
204
* signatures, only the signature data is returned. The original message
205
* text may be distributed separately from the signature data. This is
206
* useful for miltipart/signed email messages as per
207
* {@link http://www.ietf.org/rfc/rfc3156.txt RFC 3156}.
209
* @see Crypt_GPG::sign()
210
* @see Crypt_GPG::signFile()
212
const SIGN_MODE_DETACHED = 3;
215
// {{{ class constants for fingerprint formats
218
* No formatting is performed.
220
* Example: C3BC615AD9C766E5A85C1F2716D27458B1BBA1C4
222
* @see Crypt_GPG::getFingerprint()
224
const FORMAT_NONE = 1;
227
* Fingerprint is formatted in the format used by the GnuPG gpg command's
230
* Example: C3BC 615A D9C7 66E5 A85C 1F27 16D2 7458 B1BB A1C4
232
* @see Crypt_GPG::getFingerprint()
234
const FORMAT_CANONICAL = 2;
237
* Fingerprint is formatted in the format used when displaying X.509
240
* Example: C3:BC:61:5A:D9:C7:66:E5:A8:5C:1F:27:16:D2:74:58:B1:BB:A1:C4
242
* @see Crypt_GPG::getFingerprint()
244
const FORMAT_X509 = 3;
247
// {{{ other class constants
250
* URI at which package bugs may be reported.
252
const BUG_URI = 'http://pear.php.net/bugs/report.php?package=Crypt_GPG';
255
// {{{ protected class properties
258
* Engine used to control the GPG subprocess
260
* @var Crypt_GPG_Engine
262
* @see Crypt_GPG::setEngine()
264
protected $engine = null;
267
* Keys used to encrypt
269
* The array is of the form:
273
* 'fingerprint' => $fingerprint,
274
* 'passphrase' => null
280
* @see Crypt_GPG::addEncryptKey()
281
* @see Crypt_GPG::clearEncryptKeys()
283
protected $encryptKeys = array();
286
* Keys used to decrypt
288
* The array is of the form:
292
* 'fingerprint' => $fingerprint,
293
* 'passphrase' => $passphrase
299
* @see Crypt_GPG::addSignKey()
300
* @see Crypt_GPG::clearSignKeys()
302
protected $signKeys = array();
307
* The array is of the form:
311
* 'fingerprint' => $fingerprint,
312
* 'passphrase' => $passphrase
318
* @see Crypt_GPG::addDecryptKey()
319
* @see Crypt_GPG::clearDecryptKeys()
321
protected $decryptKeys = array();
327
* Creates a new GPG object
329
* Available options are:
331
* - <kbd>string homedir</kbd> - the directory where the GPG
332
* keyring files are stored. If not
333
* specified, Crypt_GPG uses the
334
* default of <kbd>~/.gnupg</kbd>.
335
* - <kbd>string publicKeyring</kbd> - the file path of the public
336
* keyring. Use this if the public
337
* keyring is not in the homedir, or
338
* if the keyring is in a directory
339
* not writable by the process
340
* invoking GPG (like Apache). Then
341
* you can specify the path to the
342
* keyring with this option
343
* (/foo/bar/pubring.gpg), and specify
344
* a writable directory (like /tmp)
345
* using the <i>homedir</i> option.
346
* - <kbd>string privateKeyring</kbd> - the file path of the private
347
* keyring. Use this if the private
348
* keyring is not in the homedir, or
349
* if the keyring is in a directory
350
* not writable by the process
351
* invoking GPG (like Apache). Then
352
* you can specify the path to the
353
* keyring with this option
354
* (/foo/bar/secring.gpg), and specify
355
* a writable directory (like /tmp)
356
* using the <i>homedir</i> option.
357
* - <kbd>string trustDb</kbd> - the file path of the web-of-trust
358
* database. Use this if the trust
359
* database is not in the homedir, or
360
* if the database is in a directory
361
* not writable by the process
362
* invoking GPG (like Apache). Then
363
* you can specify the path to the
364
* trust database with this option
365
* (/foo/bar/trustdb.gpg), and specify
366
* a writable directory (like /tmp)
367
* using the <i>homedir</i> option.
368
* - <kbd>string binary</kbd> - the location of the GPG binary. If
369
* not specified, the driver attempts
370
* to auto-detect the GPG binary
371
* location using a list of known
372
* default locations for the current
373
* operating system. The option
374
* <kbd>gpgBinary</kbd> is a
375
* deprecated alias for this option.
376
* - <kbd>boolean debug</kbd> - whether or not to use debug mode.
377
* When debug mode is on, all
378
* communication to and from the GPG
379
* subprocess is logged. This can be
381
* @param array $options optional. An array of options used to create the
382
* GPG object. All options are optional and are
383
* represented as key-value pairs.
385
* @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
386
* and cannot be created. This can happen if <kbd>homedir</kbd> is
387
* not specified, Crypt_GPG is run as the web user, and the web
388
* user has no home directory. This exception is also thrown if any
389
* of the options <kbd>publicKeyring</kbd>,
390
* <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
391
* specified but the files do not exist or are are not readable.
392
* This can happen if the user running the Crypt_GPG process (for
393
* example, the Apache user) does not have permission to read the
396
* @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
397
* if no <kbd>binary</kbd> is provided and no suitable binary could
400
public function __construct(array $options = array())
402
$this->setEngine(new Crypt_GPG_Engine($options));
409
* Imports a public or private key into the keyring
411
* Keys may be removed from the keyring using
412
* {@link Crypt_GPG::deletePublicKey()} or
413
* {@link Crypt_GPG::deletePrivateKey()}.
415
* @param string $data the key data to be imported.
417
* @return array an associative array containing the following elements:
418
* - <kbd>fingerprint</kbd> - the fingerprint of the
420
* - <kbd>public_imported</kbd> - the number of public
422
* - <kbd>public_unchanged</kbd> - the number of unchanged
424
* - <kbd>private_imported</kbd> - the number of private
426
* - <kbd>private_unchanged</kbd> - the number of unchanged
429
* @throws Crypt_GPG_NoDataException if the key data is missing or if the
430
* data is is not valid key data.
432
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
433
* Use the <kbd>debug</kbd> option and file a bug report if these
436
public function importKey($data)
438
return $this->_importKey($data, false);
442
// {{{ importKeyFile()
445
* Imports a public or private key file into the keyring
447
* Keys may be removed from the keyring using
448
* {@link Crypt_GPG::deletePublicKey()} or
449
* {@link Crypt_GPG::deletePrivateKey()}.
451
* @param string $filename the key file to be imported.
453
* @return array an associative array containing the following elements:
454
* - <kbd>fingerprint</kbd> - the fingerprint of the
456
* - <kbd>public_imported</kbd> - the number of public
458
* - <kbd>public_unchanged</kbd> - the number of unchanged
460
* - <kbd>private_imported</kbd> - the number of private
462
* - <kbd>private_unchanged</kbd> - the number of unchanged
466
* @throws Crypt_GPG_NoDataException if the key data is missing or if the
467
* data is is not valid key data.
469
* @throws Crypt_GPG_FileException if the key file is not readable.
471
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
472
* Use the <kbd>debug</kbd> option and file a bug report if these
475
public function importKeyFile($filename)
477
return $this->_importKey($filename, true);
481
// {{{ exportPublicKey()
484
* Exports a public key from the keyring
486
* The exported key remains on the keyring. To delete the public key, use
487
* {@link Crypt_GPG::deletePublicKey()}.
489
* If more than one key fingerprint is available for the specified
490
* <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
491
* first public key is exported.
493
* @param string $keyId either the full uid of the public key, the email
494
* part of the uid of the public key or the key id of
495
* the public key. For example,
496
* "Test User (example) <test@example.com>",
497
* "test@example.com" or a hexadecimal string.
498
* @param boolean $armor optional. If true, ASCII armored data is returned;
499
* otherwise, binary data is returned. Defaults to
502
* @return string the public key data.
504
* @throws Crypt_GPG_KeyNotFoundException if a public key with the given
505
* <kbd>$keyId</kbd> is not found.
507
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
508
* Use the <kbd>debug</kbd> option and file a bug report if these
511
public function exportPublicKey($keyId, $armor = true)
513
$fingerprint = $this->getFingerprint($keyId);
515
if ($fingerprint === null) {
516
throw new Crypt_GPG_KeyNotFoundException(
517
'Public key not found: ' . $keyId,
518
Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
522
$operation = '--export ' . escapeshellarg($fingerprint);
523
$arguments = ($armor) ? array('--armor') : array();
525
$this->engine->reset();
526
$this->engine->setOutput($keyData);
527
$this->engine->setOperation($operation, $arguments);
528
$this->engine->run();
530
$code = $this->engine->getErrorCode();
532
if ($code !== Crypt_GPG::ERROR_NONE) {
533
throw new Crypt_GPG_Exception(
534
'Unknown error exporting public key. Please use the ' .
535
'\'debug\' option when creating the Crypt_GPG object, and ' .
536
'file a bug report at ' . self::BUG_URI, $code);
543
// {{{ deletePublicKey()
546
* Deletes a public key from the keyring
548
* If more than one key fingerprint is available for the specified
549
* <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
550
* first public key is deleted.
552
* The private key must be deleted first or an exception will be thrown.
553
* See {@link Crypt_GPG::deletePrivateKey()}.
555
* @param string $keyId either the full uid of the public key, the email
556
* part of the uid of the public key or the key id of
557
* the public key. For example,
558
* "Test User (example) <test@example.com>",
559
* "test@example.com" or a hexadecimal string.
563
* @throws Crypt_GPG_KeyNotFoundException if a public key with the given
564
* <kbd>$keyId</kbd> is not found.
566
* @throws Crypt_GPG_DeletePrivateKeyException if the specified public key
567
* has an associated private key on the keyring. The private key
568
* must be deleted first.
570
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
571
* Use the <kbd>debug</kbd> option and file a bug report if these
574
public function deletePublicKey($keyId)
576
$fingerprint = $this->getFingerprint($keyId);
578
if ($fingerprint === null) {
579
throw new Crypt_GPG_KeyNotFoundException(
580
'Public key not found: ' . $keyId,
581
Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
584
$operation = '--delete-key ' . escapeshellarg($fingerprint);
590
$this->engine->reset();
591
$this->engine->setOperation($operation, $arguments);
592
$this->engine->run();
594
$code = $this->engine->getErrorCode();
597
case Crypt_GPG::ERROR_NONE:
599
case Crypt_GPG::ERROR_DELETE_PRIVATE_KEY:
600
throw new Crypt_GPG_DeletePrivateKeyException(
601
'Private key must be deleted before public key can be ' .
602
'deleted.', $code, $keyId);
604
throw new Crypt_GPG_Exception(
605
'Unknown error deleting public key. Please use the ' .
606
'\'debug\' option when creating the Crypt_GPG object, and ' .
607
'file a bug report at ' . self::BUG_URI, $code);
612
// {{{ deletePrivateKey()
615
* Deletes a private key from the keyring
617
* If more than one key fingerprint is available for the specified
618
* <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
619
* first private key is deleted.
621
* Calls GPG with the <kbd>--delete-secret-key</kbd> command.
623
* @param string $keyId either the full uid of the private key, the email
624
* part of the uid of the private key or the key id of
625
* the private key. For example,
626
* "Test User (example) <test@example.com>",
627
* "test@example.com" or a hexadecimal string.
631
* @throws Crypt_GPG_KeyNotFoundException if a private key with the given
632
* <kbd>$keyId</kbd> is not found.
634
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
635
* Use the <kbd>debug</kbd> option and file a bug report if these
638
public function deletePrivateKey($keyId)
640
$fingerprint = $this->getFingerprint($keyId);
642
if ($fingerprint === null) {
643
throw new Crypt_GPG_KeyNotFoundException(
644
'Private key not found: ' . $keyId,
645
Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
648
$operation = '--delete-secret-key ' . escapeshellarg($fingerprint);
654
$this->engine->reset();
655
$this->engine->setOperation($operation, $arguments);
656
$this->engine->run();
658
$code = $this->engine->getErrorCode();
661
case Crypt_GPG::ERROR_NONE:
663
case Crypt_GPG::ERROR_KEY_NOT_FOUND:
664
throw new Crypt_GPG_KeyNotFoundException(
665
'Private key not found: ' . $keyId,
668
throw new Crypt_GPG_Exception(
669
'Unknown error deleting private key. Please use the ' .
670
'\'debug\' option when creating the Crypt_GPG object, and ' .
671
'file a bug report at ' . self::BUG_URI, $code);
679
* Gets the available keys in the keyring
681
* Calls GPG with the <kbd>--list-keys</kbd> command and grabs keys. See
682
* the first section of <b>doc/DETAILS</b> in the
683
* {@link http://www.gnupg.org/download/ GPG package} for a detailed
684
* description of how the GPG command output is parsed.
686
* @param string $keyId optional. Only keys with that match the specified
687
* pattern are returned. The pattern may be part of
688
* a user id, a key id or a key fingerprint. If not
689
* specified, all keys are returned.
691
* @return array an array of {@link Crypt_GPG_Key} objects. If no keys
692
* match the specified <kbd>$keyId</kbd> an empty array is
695
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
696
* Use the <kbd>debug</kbd> option and file a bug report if these
701
public function getKeys($keyId = '')
703
// get private key fingerprints
705
$operation = '--list-secret-keys';
707
$operation = '--list-secret-keys ' . escapeshellarg($keyId);
712
'--with-fingerprint',
713
'--with-fingerprint',
719
$this->engine->reset();
720
$this->engine->setOutput($output);
721
$this->engine->setOperation($operation, $arguments);
722
$this->engine->run();
724
$code = $this->engine->getErrorCode();
727
case Crypt_GPG::ERROR_NONE:
728
case Crypt_GPG::ERROR_KEY_NOT_FOUND:
729
// ignore not found key errors
732
throw new Crypt_GPG_Exception(
733
'Unknown error getting keys. Please use the \'debug\' option ' .
734
'when creating the Crypt_GPG object, and file a bug report ' .
735
'at ' . self::BUG_URI, $code);
738
$privateKeyFingerprints = array();
740
$lines = explode(PHP_EOL, $output);
741
foreach ($lines as $line) {
742
$lineExp = explode(':', $line);
743
if ($lineExp[0] == 'fpr') {
744
$privateKeyFingerprints[] = $lineExp[9];
750
$operation = '--list-public-keys';
752
$operation = '--list-public-keys ' . escapeshellarg($keyId);
757
$this->engine->reset();
758
$this->engine->setOutput($output);
759
$this->engine->setOperation($operation, $arguments);
760
$this->engine->run();
762
$code = $this->engine->getErrorCode();
765
case Crypt_GPG::ERROR_NONE:
766
case Crypt_GPG::ERROR_KEY_NOT_FOUND:
767
// ignore not found key errors
770
throw new Crypt_GPG_Exception(
771
'Unknown error getting keys. Please use the \'debug\' option ' .
772
'when creating the Crypt_GPG object, and file a bug report ' .
773
'at ' . self::BUG_URI, $code);
778
$key = null; // current key
779
$subKey = null; // current sub-key
781
$lines = explode(PHP_EOL, $output);
782
foreach ($lines as $line) {
783
$lineExp = explode(':', $line);
785
if ($lineExp[0] == 'pub') {
787
// new primary key means last key should be added to the array
792
$key = new Crypt_GPG_Key();
794
$subKey = Crypt_GPG_SubKey::parse($line);
795
$key->addSubKey($subKey);
797
} elseif ($lineExp[0] == 'sub') {
799
$subKey = Crypt_GPG_SubKey::parse($line);
800
$key->addSubKey($subKey);
802
} elseif ($lineExp[0] == 'fpr') {
804
$fingerprint = $lineExp[9];
806
// set current sub-key fingerprint
807
$subKey->setFingerprint($fingerprint);
809
// if private key exists, set has private to true
810
if (in_array($fingerprint, $privateKeyFingerprints)) {
811
$subKey->setHasPrivate(true);
814
} elseif ($lineExp[0] == 'uid') {
816
$string = stripcslashes($lineExp[9]); // as per documentation
817
$key->addUserId(Crypt_GPG_UserId::parse($string));
831
// {{{ getFingerprint()
834
* Gets a key fingerprint from the keyring
836
* If more than one key fingerprint is available (for example, if you use
837
* a non-unique user id) only the first key fingerprint is returned.
839
* Calls the GPG <kbd>--list-keys</kbd> command with the
840
* <kbd>--with-fingerprint</kbd> option to retrieve a public key
843
* @param string $keyId either the full user id of the key, the email
844
* part of the user id of the key, or the key id of
845
* the key. For example,
846
* "Test User (example) <test@example.com>",
847
* "test@example.com" or a hexadecimal string.
848
* @param integer $format optional. How the fingerprint should be formatted.
849
* Use {@link Crypt_GPG::FORMAT_X509} for X.509
850
* certificate format,
851
* {@link Crypt_GPG::FORMAT_CANONICAL} for the format
852
* used by GnuPG output and
853
* {@link Crypt_GPG::FORMAT_NONE} for no formatting.
854
* Defaults to <code>Crypt_GPG::FORMAT_NONE</code>.
856
* @return string the fingerprint of the key, or null if no fingerprint
857
* is found for the given <kbd>$keyId</kbd>.
859
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
860
* Use the <kbd>debug</kbd> option and file a bug report if these
863
public function getFingerprint($keyId, $format = Crypt_GPG::FORMAT_NONE)
866
$operation = '--list-keys ' . escapeshellarg($keyId);
872
$this->engine->reset();
873
$this->engine->setOutput($output);
874
$this->engine->setOperation($operation, $arguments);
875
$this->engine->run();
877
$code = $this->engine->getErrorCode();
880
case Crypt_GPG::ERROR_NONE:
881
case Crypt_GPG::ERROR_KEY_NOT_FOUND:
882
// ignore not found key errors
885
throw new Crypt_GPG_Exception(
886
'Unknown error getting key fingerprint. Please use the ' .
887
'\'debug\' option when creating the Crypt_GPG object, and ' .
888
'file a bug report at ' . self::BUG_URI, $code);
893
$lines = explode(PHP_EOL, $output);
894
foreach ($lines as $line) {
895
if (substr($line, 0, 3) == 'fpr') {
896
$lineExp = explode(':', $line);
897
$fingerprint = $lineExp[9];
900
case Crypt_GPG::FORMAT_CANONICAL:
901
$fingerprintExp = str_split($fingerprint, 4);
902
$format = '%s %s %s %s %s %s %s %s %s %s';
903
$fingerprint = vsprintf($format, $fingerprintExp);
906
case Crypt_GPG::FORMAT_X509:
907
$fingerprintExp = str_split($fingerprint, 2);
908
$fingerprint = implode(':', $fingerprintExp);
923
* Encrypts string data
925
* Data is ASCII armored by default but may optionally be returned as
928
* @param string $data the data to be encrypted.
929
* @param boolean $armor optional. If true, ASCII armored data is returned;
930
* otherwise, binary data is returned. Defaults to
933
* @return string the encrypted data.
935
* @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
936
* See {@link Crypt_GPG::addEncryptKey()}.
938
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
939
* Use the <kbd>debug</kbd> option and file a bug report if these
944
public function encrypt($data, $armor = true)
946
return $this->_encrypt($data, false, null, $armor);
955
* Encrypted data is ASCII armored by default but may optionally be saved
958
* @param string $filename the filename of the file to encrypt.
959
* @param string $encryptedFile optional. The filename of the file in
960
* which to store the encrypted data. If null
961
* or unspecified, the encrypted data is
962
* returned as a string.
963
* @param boolean $armor optional. If true, ASCII armored data is
964
* returned; otherwise, binary data is
965
* returned. Defaults to true.
967
* @return void|string if the <kbd>$encryptedFile</kbd> parameter is null,
968
* a string containing the encrypted data is returned.
970
* @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
971
* See {@link Crypt_GPG::addEncryptKey()}.
973
* @throws Crypt_GPG_FileException if the output file is not writeable or
974
* if the input file is not readable.
976
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
977
* Use the <kbd>debug</kbd> option and file a bug report if these
980
public function encryptFile($filename, $encryptedFile = null, $armor = true)
982
return $this->_encrypt($filename, true, $encryptedFile, $armor);
986
// {{{ encryptAndSign()
989
* Encrypts and signs data
991
* Data is encrypted and signed in a single pass.
993
* NOTE: Until GnuPG version 1.4.10, it was not possible to verify
994
* encrypted-signed data without decrypting it at the same time. If you try
995
* to use {@link Crypt_GPG::verify()} method on encrypted-signed data with
996
* earlier GnuPG versions, you will get an error. Please use
997
* {@link Crypt_GPG::decryptAndVerify()} to verify encrypted-signed data.
999
* @param string $data the data to be encrypted and signed.
1000
* @param boolean $armor optional. If true, ASCII armored data is returned;
1001
* otherwise, binary data is returned. Defaults to
1004
* @return string the encrypted signed data.
1006
* @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
1007
* or if no signing key is specified. See
1008
* {@link Crypt_GPG::addEncryptKey()} and
1009
* {@link Crypt_GPG::addSignKey()}.
1011
* @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
1012
* incorrect or if a required passphrase is not specified.
1014
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1015
* Use the <kbd>debug</kbd> option and file a bug report if these
1018
* @see Crypt_GPG::decryptAndVerify()
1020
public function encryptAndSign($data, $armor = true)
1022
return $this->_encryptAndSign($data, false, null, $armor);
1026
// {{{ encryptAndSignFile()
1029
* Encrypts and signs a file
1031
* The file is encrypted and signed in a single pass.
1033
* NOTE: Until GnuPG version 1.4.10, it was not possible to verify
1034
* encrypted-signed files without decrypting them at the same time. If you
1035
* try to use {@link Crypt_GPG::verify()} method on encrypted-signed files
1036
* with earlier GnuPG versions, you will get an error. Please use
1037
* {@link Crypt_GPG::decryptAndVerifyFile()} to verify encrypted-signed
1040
* @param string $filename the name of the file containing the data to
1041
* be encrypted and signed.
1042
* @param string $signedFile optional. The name of the file in which the
1043
* encrypted, signed data should be stored. If
1044
* null or unspecified, the encrypted, signed
1045
* data is returned as a string.
1046
* @param boolean $armor optional. If true, ASCII armored data is
1047
* returned; otherwise, binary data is returned.
1050
* @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
1051
* string containing the encrypted, signed data is
1054
* @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
1055
* or if no signing key is specified. See
1056
* {@link Crypt_GPG::addEncryptKey()} and
1057
* {@link Crypt_GPG::addSignKey()}.
1059
* @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
1060
* incorrect or if a required passphrase is not specified.
1062
* @throws Crypt_GPG_FileException if the output file is not writeable or
1063
* if the input file is not readable.
1065
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1066
* Use the <kbd>debug</kbd> option and file a bug report if these
1069
* @see Crypt_GPG::decryptAndVerifyFile()
1071
public function encryptAndSignFile($filename, $signedFile = null,
1074
return $this->_encryptAndSign($filename, true, $signedFile, $armor);
1081
* Decrypts string data
1083
* This method assumes the required private key is available in the keyring
1084
* and throws an exception if the private key is not available. To add a
1085
* private key to the keyring, use the {@link Crypt_GPG::importKey()} or
1086
* {@link Crypt_GPG::importKeyFile()} methods.
1088
* @param string $encryptedData the data to be decrypted.
1090
* @return string the decrypted data.
1092
* @throws Crypt_GPG_KeyNotFoundException if the private key needed to
1093
* decrypt the data is not in the user's keyring.
1095
* @throws Crypt_GPG_NoDataException if specified data does not contain
1096
* GPG encrypted data.
1098
* @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1099
* incorrect or if a required passphrase is not specified. See
1100
* {@link Crypt_GPG::addDecryptKey()}.
1102
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1103
* Use the <kbd>debug</kbd> option and file a bug report if these
1106
public function decrypt($encryptedData)
1108
return $this->_decrypt($encryptedData, false, null);
1112
// {{{ decryptFile()
1117
* This method assumes the required private key is available in the keyring
1118
* and throws an exception if the private key is not available. To add a
1119
* private key to the keyring, use the {@link Crypt_GPG::importKey()} or
1120
* {@link Crypt_GPG::importKeyFile()} methods.
1122
* @param string $encryptedFile the name of the encrypted file data to
1124
* @param string $decryptedFile optional. The name of the file to which the
1125
* decrypted data should be written. If null
1126
* or unspecified, the decrypted data is
1127
* returned as a string.
1129
* @return void|string if the <kbd>$decryptedFile</kbd> parameter is null,
1130
* a string containing the decrypted data is returned.
1132
* @throws Crypt_GPG_KeyNotFoundException if the private key needed to
1133
* decrypt the data is not in the user's keyring.
1135
* @throws Crypt_GPG_NoDataException if specified data does not contain
1136
* GPG encrypted data.
1138
* @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1139
* incorrect or if a required passphrase is not specified. See
1140
* {@link Crypt_GPG::addDecryptKey()}.
1142
* @throws Crypt_GPG_FileException if the output file is not writeable or
1143
* if the input file is not readable.
1145
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1146
* Use the <kbd>debug</kbd> option and file a bug report if these
1149
public function decryptFile($encryptedFile, $decryptedFile = null)
1151
return $this->_decrypt($encryptedFile, true, $decryptedFile);
1155
// {{{ decryptAndVerify()
1158
* Decrypts and verifies string data
1160
* This method assumes the required private key is available in the keyring
1161
* and throws an exception if the private key is not available. To add a
1162
* private key to the keyring, use the {@link Crypt_GPG::importKey()} or
1163
* {@link Crypt_GPG::importKeyFile()} methods.
1165
* @param string $encryptedData the encrypted, signed data to be decrypted
1168
* @return array two element array. The array has an element 'data'
1169
* containing the decrypted data and an element
1170
* 'signatures' containing an array of
1171
* {@link Crypt_GPG_Signature} objects for the signed data.
1173
* @throws Crypt_GPG_KeyNotFoundException if the private key needed to
1174
* decrypt the data is not in the user's keyring.
1176
* @throws Crypt_GPG_NoDataException if specified data does not contain
1177
* GPG encrypted data.
1179
* @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1180
* incorrect or if a required passphrase is not specified. See
1181
* {@link Crypt_GPG::addDecryptKey()}.
1183
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1184
* Use the <kbd>debug</kbd> option and file a bug report if these
1187
public function decryptAndVerify($encryptedData)
1189
return $this->_decryptAndVerify($encryptedData, false, null);
1193
// {{{ decryptAndVerifyFile()
1196
* Decrypts and verifies a signed, encrypted file
1198
* This method assumes the required private key is available in the keyring
1199
* and throws an exception if the private key is not available. To add a
1200
* private key to the keyring, use the {@link Crypt_GPG::importKey()} or
1201
* {@link Crypt_GPG::importKeyFile()} methods.
1203
* @param string $encryptedFile the name of the signed, encrypted file to
1204
* to decrypt and verify.
1205
* @param string $decryptedFile optional. The name of the file to which the
1206
* decrypted data should be written. If null
1207
* or unspecified, the decrypted data is
1208
* returned in the results array.
1210
* @return array two element array. The array has an element 'data'
1211
* containing the decrypted data and an element
1212
* 'signatures' containing an array of
1213
* {@link Crypt_GPG_Signature} objects for the signed data.
1214
* If the decrypted data is written to a file, the 'data'
1217
* @throws Crypt_GPG_KeyNotFoundException if the private key needed to
1218
* decrypt the data is not in the user's keyring.
1220
* @throws Crypt_GPG_NoDataException if specified data does not contain
1221
* GPG encrypted data.
1223
* @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1224
* incorrect or if a required passphrase is not specified. See
1225
* {@link Crypt_GPG::addDecryptKey()}.
1227
* @throws Crypt_GPG_FileException if the output file is not writeable or
1228
* if the input file is not readable.
1230
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1231
* Use the <kbd>debug</kbd> option and file a bug report if these
1234
public function decryptAndVerifyFile($encryptedFile, $decryptedFile = null)
1236
return $this->_decryptAndVerify($encryptedFile, true, $decryptedFile);
1245
* Data may be signed using any one of the three available signing modes:
1246
* - {@link Crypt_GPG::SIGN_MODE_NORMAL}
1247
* - {@link Crypt_GPG::SIGN_MODE_CLEAR}
1248
* - {@link Crypt_GPG::SIGN_MODE_DETACHED}
1250
* @param string $data the data to be signed.
1251
* @param boolean $mode optional. The data signing mode to use. Should
1252
* be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
1253
* {@link Crypt_GPG::SIGN_MODE_CLEAR} or
1254
* {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
1255
* specified, defaults to
1256
* <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
1257
* @param boolean $armor optional. If true, ASCII armored data is
1258
* returned; otherwise, binary data is returned.
1259
* Defaults to true. This has no effect if the
1260
* mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
1262
* @param boolean $textmode optional. If true, line-breaks in signed data
1263
* are normalized. Use this option when signing
1264
* e-mail, or for greater compatibility between
1265
* systems with different line-break formats.
1266
* Defaults to false. This has no effect if the
1267
* mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
1268
* used as clear-signing always uses textmode.
1270
* @return string the signed data, or the signature data if a detached
1271
* signature is requested.
1273
* @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
1274
* See {@link Crypt_GPG::addSignKey()}.
1276
* @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
1277
* incorrect or if a required passphrase is not specified.
1279
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1280
* Use the <kbd>debug</kbd> option and file a bug report if these
1283
public function sign($data, $mode = Crypt_GPG::SIGN_MODE_NORMAL,
1284
$armor = true, $textmode = false
1286
return $this->_sign($data, false, null, $mode, $armor, $textmode);
1295
* The file may be signed using any one of the three available signing
1297
* - {@link Crypt_GPG::SIGN_MODE_NORMAL}
1298
* - {@link Crypt_GPG::SIGN_MODE_CLEAR}
1299
* - {@link Crypt_GPG::SIGN_MODE_DETACHED}
1301
* @param string $filename the name of the file containing the data to
1303
* @param string $signedFile optional. The name of the file in which the
1304
* signed data should be stored. If null or
1305
* unspecified, the signed data is returned as a
1307
* @param boolean $mode optional. The data signing mode to use. Should
1308
* be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
1309
* {@link Crypt_GPG::SIGN_MODE_CLEAR} or
1310
* {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
1311
* specified, defaults to
1312
* <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
1313
* @param boolean $armor optional. If true, ASCII armored data is
1314
* returned; otherwise, binary data is returned.
1315
* Defaults to true. This has no effect if the
1316
* mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
1318
* @param boolean $textmode optional. If true, line-breaks in signed data
1319
* are normalized. Use this option when signing
1320
* e-mail, or for greater compatibility between
1321
* systems with different line-break formats.
1322
* Defaults to false. This has no effect if the
1323
* mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
1324
* used as clear-signing always uses textmode.
1326
* @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
1327
* string containing the signed data (or the signature
1328
* data if a detached signature is requested) is
1331
* @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
1332
* See {@link Crypt_GPG::addSignKey()}.
1334
* @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
1335
* incorrect or if a required passphrase is not specified.
1337
* @throws Crypt_GPG_FileException if the output file is not writeable or
1338
* if the input file is not readable.
1340
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1341
* Use the <kbd>debug</kbd> option and file a bug report if these
1344
public function signFile($filename, $signedFile = null,
1345
$mode = Crypt_GPG::SIGN_MODE_NORMAL, $armor = true, $textmode = false
1347
return $this->_sign(
1361
* Verifies signed data
1363
* The {@link Crypt_GPG::decrypt()} method may be used to get the original
1364
* message if the signed data is not clearsigned and does not use a
1365
* detached signature.
1367
* @param string $signedData the signed data to be verified.
1368
* @param string $signature optional. If verifying data signed using a
1369
* detached signature, this must be the detached
1370
* signature data. The data that was signed is
1371
* specified in <kbd>$signedData</kbd>.
1373
* @return array an array of {@link Crypt_GPG_Signature} objects for the
1374
* signed data. For each signature that is valid, the
1375
* {@link Crypt_GPG_Signature::isValid()} will return true.
1377
* @throws Crypt_GPG_NoDataException if the provided data is not signed
1380
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1381
* Use the <kbd>debug</kbd> option and file a bug report if these
1384
* @see Crypt_GPG_Signature
1386
public function verify($signedData, $signature = '')
1388
return $this->_verify($signedData, false, $signature);
1395
* Verifies a signed file
1397
* The {@link Crypt_GPG::decryptFile()} method may be used to get the
1398
* original message if the signed data is not clearsigned and does not use
1399
* a detached signature.
1401
* @param string $filename the signed file to be verified.
1402
* @param string $signature optional. If verifying a file signed using a
1403
* detached signature, this must be the detached
1404
* signature data. The file that was signed is
1405
* specified in <kbd>$filename</kbd>.
1407
* @return array an array of {@link Crypt_GPG_Signature} objects for the
1408
* signed data. For each signature that is valid, the
1409
* {@link Crypt_GPG_Signature::isValid()} will return true.
1411
* @throws Crypt_GPG_NoDataException if the provided data is not signed
1414
* @throws Crypt_GPG_FileException if the input file is not readable.
1416
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1417
* Use the <kbd>debug</kbd> option and file a bug report if these
1420
* @see Crypt_GPG_Signature
1422
public function verifyFile($filename, $signature = '')
1424
return $this->_verify($filename, true, $signature);
1428
// {{{ addDecryptKey()
1431
* Adds a key to use for decryption
1433
* @param mixed $key the key to use. This may be a key identifier,
1434
* user id, fingerprint, {@link Crypt_GPG_Key} or
1435
* {@link Crypt_GPG_SubKey}. The key must be able
1437
* @param string $passphrase optional. The passphrase of the key required
1442
* @see Crypt_GPG::decrypt()
1443
* @see Crypt_GPG::decryptFile()
1444
* @see Crypt_GPG::clearDecryptKeys()
1445
* @see Crypt_GPG::_addKey()
1446
* @see Crypt_GPG_DecryptStatusHandler
1448
* @sensitive $passphrase
1450
public function addDecryptKey($key, $passphrase = null)
1452
$this->_addKey($this->decryptKeys, true, false, $key, $passphrase);
1456
// {{{ addEncryptKey()
1459
* Adds a key to use for encryption
1461
* @param mixed $key the key to use. This may be a key identifier, user id
1462
* user id, fingerprint, {@link Crypt_GPG_Key} or
1463
* {@link Crypt_GPG_SubKey}. The key must be able to
1468
* @see Crypt_GPG::encrypt()
1469
* @see Crypt_GPG::encryptFile()
1470
* @see Crypt_GPG::clearEncryptKeys()
1471
* @see Crypt_GPG::_addKey()
1473
public function addEncryptKey($key)
1475
$this->_addKey($this->encryptKeys, true, false, $key);
1482
* Adds a key to use for signing
1484
* @param mixed $key the key to use. This may be a key identifier,
1485
* user id, fingerprint, {@link Crypt_GPG_Key} or
1486
* {@link Crypt_GPG_SubKey}. The key must be able
1488
* @param string $passphrase optional. The passphrase of the key required
1493
* @see Crypt_GPG::sign()
1494
* @see Crypt_GPG::signFile()
1495
* @see Crypt_GPG::clearSignKeys()
1496
* @see Crypt_GPG::handleSignStatus()
1497
* @see Crypt_GPG::_addKey()
1499
* @sensitive $passphrase
1501
public function addSignKey($key, $passphrase = null)
1503
$this->_addKey($this->signKeys, false, true, $key, $passphrase);
1507
// {{{ clearDecryptKeys()
1510
* Clears all decryption keys
1514
* @see Crypt_GPG::decrypt()
1515
* @see Crypt_GPG::addDecryptKey()
1517
public function clearDecryptKeys()
1519
$this->decryptKeys = array();
1523
// {{{ clearEncryptKeys()
1526
* Clears all encryption keys
1530
* @see Crypt_GPG::encrypt()
1531
* @see Crypt_GPG::addEncryptKey()
1533
public function clearEncryptKeys()
1535
$this->encryptKeys = array();
1539
// {{{ clearSignKeys()
1542
* Clears all signing keys
1546
* @see Crypt_GPG::sign()
1547
* @see Crypt_GPG::addSignKey()
1549
public function clearSignKeys()
1551
$this->signKeys = array();
1555
// {{{ handleSignStatus()
1558
* Handles the status output from GPG for the sign operation
1560
* This method is responsible for sending the passphrase commands when
1561
* required by the {@link Crypt_GPG::sign()} method. See <b>doc/DETAILS</b>
1562
* in the {@link http://www.gnupg.org/download/ GPG distribution} for
1563
* detailed information on GPG's status output.
1565
* @param string $line the status line to handle.
1569
* @see Crypt_GPG::sign()
1571
public function handleSignStatus($line)
1573
$tokens = explode(' ', $line);
1574
switch ($tokens[0]) {
1575
case 'NEED_PASSPHRASE':
1576
$subKeyId = $tokens[1];
1577
if (array_key_exists($subKeyId, $this->signKeys)) {
1578
$passphrase = $this->signKeys[$subKeyId]['passphrase'];
1579
$this->engine->sendCommand($passphrase);
1581
$this->engine->sendCommand('');
1588
// {{{ handleImportKeyStatus()
1591
* Handles the status output from GPG for the import operation
1593
* This method is responsible for building the result array that is
1594
* returned from the {@link Crypt_GPG::importKey()} method. See
1595
* <b>doc/DETAILS</b> in the
1596
* {@link http://www.gnupg.org/download/ GPG distribution} for detailed
1597
* information on GPG's status output.
1599
* @param string $line the status line to handle.
1600
* @param array &$result the current result array being processed.
1604
* @see Crypt_GPG::importKey()
1605
* @see Crypt_GPG::importKeyFile()
1606
* @see Crypt_GPG_Engine::addStatusHandler()
1608
public function handleImportKeyStatus($line, array &$result)
1610
$tokens = explode(' ', $line);
1611
switch ($tokens[0]) {
1613
$result['fingerprint'] = $tokens[2];
1617
$result['public_imported'] = intval($tokens[3]);
1618
$result['public_unchanged'] = intval($tokens[5]);
1619
$result['private_imported'] = intval($tokens[11]);
1620
$result['private_unchanged'] = intval($tokens[12]);
1629
* Sets the I/O engine to use for GnuPG operations
1631
* Normally this method does not need to be used. It provides a means for
1632
* dependency injection.
1634
* @param Crypt_GPG_Engine $engine the engine to use.
1638
public function setEngine(Crypt_GPG_Engine $engine)
1640
$this->engine = $engine;
1647
* Adds a key to one of the internal key arrays
1649
* This handles resolving full key objects from the provided
1650
* <kbd>$key</kbd> value.
1652
* @param array &$array the array to which the key should be added.
1653
* @param boolean $encrypt whether or not the key must be able to
1655
* @param boolean $sign whether or not the key must be able to sign.
1656
* @param mixed $key the key to add. This may be a key identifier,
1657
* user id, fingerprint, {@link Crypt_GPG_Key} or
1658
* {@link Crypt_GPG_SubKey}.
1659
* @param string $passphrase optional. The passphrase associated with the
1664
* @sensitive $passphrase
1666
private function _addKey(array &$array, $encrypt, $sign, $key,
1671
if (is_scalar($key)) {
1672
$keys = $this->getKeys($key);
1673
if (count($keys) == 0) {
1674
throw new Crypt_GPG_KeyNotFoundException(
1675
'Key "' . $key . '" not found.', 0, $key);
1680
if ($key instanceof Crypt_GPG_Key) {
1681
if ($encrypt && !$key->canEncrypt()) {
1682
throw new InvalidArgumentException(
1683
'Key "' . $key . '" cannot encrypt.');
1686
if ($sign && !$key->canSign()) {
1687
throw new InvalidArgumentException(
1688
'Key "' . $key . '" cannot sign.');
1691
foreach ($key->getSubKeys() as $subKey) {
1692
$canEncrypt = $subKey->canEncrypt();
1693
$canSign = $subKey->canSign();
1694
if ( ($encrypt && $sign && $canEncrypt && $canSign)
1695
|| ($encrypt && !$sign && $canEncrypt)
1696
|| (!$encrypt && $sign && $canSign)
1698
// We add all subkeys that meet the requirements because we
1699
// were not told which subkey is required.
1700
$subKeys[] = $subKey;
1703
} elseif ($key instanceof Crypt_GPG_SubKey) {
1707
if (count($subKeys) === 0) {
1708
throw new InvalidArgumentException(
1709
'Key "' . $key . '" is not in a recognized format.');
1712
foreach ($subKeys as $subKey) {
1713
if ($encrypt && !$subKey->canEncrypt()) {
1714
throw new InvalidArgumentException(
1715
'Key "' . $key . '" cannot encrypt.');
1718
if ($sign && !$subKey->canSign()) {
1719
throw new InvalidArgumentException(
1720
'Key "' . $key . '" cannot sign.');
1723
$array[$subKey->getId()] = array(
1724
'fingerprint' => $subKey->getFingerprint(),
1725
'passphrase' => $passphrase
1734
* Imports a public or private key into the keyring
1736
* @param string $key the key to be imported.
1737
* @param boolean $isFile whether or not the input is a filename.
1739
* @return array an associative array containing the following elements:
1740
* - <kbd>fingerprint</kbd> - the fingerprint of the
1742
* - <kbd>public_imported</kbd> - the number of public
1744
* - <kbd>public_unchanged</kbd> - the number of unchanged
1746
* - <kbd>private_imported</kbd> - the number of private
1748
* - <kbd>private_unchanged</kbd> - the number of unchanged
1751
* @throws Crypt_GPG_NoDataException if the key data is missing or if the
1752
* data is is not valid key data.
1754
* @throws Crypt_GPG_FileException if the key file is not readable.
1756
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1757
* Use the <kbd>debug</kbd> option and file a bug report if these
1760
private function _importKey($key, $isFile)
1765
$input = @fopen($key, 'rb');
1766
if ($input === false) {
1767
throw new Crypt_GPG_FileException('Could not open key file "' .
1768
$key . '" for importing.', 0, $key);
1771
$input = strval($key);
1773
throw new Crypt_GPG_NoDataException(
1774
'No valid GPG key data found.', Crypt_GPG::ERROR_NO_DATA);
1778
$arguments = array();
1779
$version = $this->engine->getVersion();
1781
if ( version_compare($version, '1.0.5', 'ge')
1782
&& version_compare($version, '1.0.7', 'lt')
1784
$arguments[] = '--allow-secret-key-import';
1787
$this->engine->reset();
1788
$this->engine->addStatusHandler(
1789
array($this, 'handleImportKeyStatus'),
1793
$this->engine->setOperation('--import', $arguments);
1794
$this->engine->setInput($input);
1795
$this->engine->run();
1801
$code = $this->engine->getErrorCode();
1804
case Crypt_GPG::ERROR_DUPLICATE_KEY:
1805
case Crypt_GPG::ERROR_NONE:
1806
// ignore duplicate key import errors
1808
case Crypt_GPG::ERROR_NO_DATA:
1809
throw new Crypt_GPG_NoDataException(
1810
'No valid GPG key data found.', $code);
1812
throw new Crypt_GPG_Exception(
1813
'Unknown error importing GPG key. Please use the \'debug\' ' .
1814
'option when creating the Crypt_GPG object, and file a bug ' .
1815
'report at ' . self::BUG_URI, $code);
1827
* @param string $data the data to encrypt.
1828
* @param boolean $isFile whether or not the data is a filename.
1829
* @param string $outputFile the filename of the file in which to store
1830
* the encrypted data. If null, the encrypted
1831
* data is returned as a string.
1832
* @param boolean $armor if true, ASCII armored data is returned;
1833
* otherwise, binary data is returned.
1835
* @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
1836
* string containing the encrypted data is returned.
1838
* @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
1839
* See {@link Crypt_GPG::addEncryptKey()}.
1841
* @throws Crypt_GPG_FileException if the output file is not writeable or
1842
* if the input file is not readable.
1844
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1845
* Use the <kbd>debug</kbd> option and file a bug report if these
1848
private function _encrypt($data, $isFile, $outputFile, $armor)
1850
if (count($this->encryptKeys) === 0) {
1851
throw new Crypt_GPG_KeyNotFoundException(
1852
'No encryption keys specified.');
1856
$input = @fopen($data, 'rb');
1857
if ($input === false) {
1858
throw new Crypt_GPG_FileException('Could not open input file "' .
1859
$data . '" for encryption.', 0, $data);
1862
$input = strval($data);
1865
if ($outputFile === null) {
1868
$output = @fopen($outputFile, 'wb');
1869
if ($output === false) {
1873
throw new Crypt_GPG_FileException('Could not open output ' .
1874
'file "' . $outputFile . '" for storing encrypted data.',
1879
$arguments = ($armor) ? array('--armor') : array();
1880
foreach ($this->encryptKeys as $key) {
1881
$arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
1884
$this->engine->reset();
1885
$this->engine->setInput($input);
1886
$this->engine->setOutput($output);
1887
$this->engine->setOperation('--encrypt', $arguments);
1888
$this->engine->run();
1894
if ($outputFile !== null) {
1898
$code = $this->engine->getErrorCode();
1900
if ($code !== Crypt_GPG::ERROR_NONE) {
1901
throw new Crypt_GPG_Exception(
1902
'Unknown error encrypting data. Please use the \'debug\' ' .
1903
'option when creating the Crypt_GPG object, and file a bug ' .
1904
'report at ' . self::BUG_URI, $code);
1907
if ($outputFile === null) {
1918
* @param string $data the data to be decrypted.
1919
* @param boolean $isFile whether or not the data is a filename.
1920
* @param string $outputFile the name of the file to which the decrypted
1921
* data should be written. If null, the decrypted
1922
* data is returned as a string.
1924
* @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
1925
* string containing the decrypted data is returned.
1927
* @throws Crypt_GPG_KeyNotFoundException if the private key needed to
1928
* decrypt the data is not in the user's keyring.
1930
* @throws Crypt_GPG_NoDataException if specified data does not contain
1931
* GPG encrypted data.
1933
* @throws Crypt_GPG_BadPassphraseException if a required passphrase is
1934
* incorrect or if a required passphrase is not specified. See
1935
* {@link Crypt_GPG::addDecryptKey()}.
1937
* @throws Crypt_GPG_FileException if the output file is not writeable or
1938
* if the input file is not readable.
1940
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
1941
* Use the <kbd>debug</kbd> option and file a bug report if these
1944
private function _decrypt($data, $isFile, $outputFile)
1947
$input = @fopen($data, 'rb');
1948
if ($input === false) {
1949
throw new Crypt_GPG_FileException('Could not open input file "' .
1950
$data . '" for decryption.', 0, $data);
1953
$input = strval($data);
1955
throw new Crypt_GPG_NoDataException(
1956
'Cannot decrypt data. No PGP encrypted data was found in '.
1957
'the provided data.', Crypt_GPG::ERROR_NO_DATA);
1961
if ($outputFile === null) {
1964
$output = @fopen($outputFile, 'wb');
1965
if ($output === false) {
1969
throw new Crypt_GPG_FileException('Could not open output ' .
1970
'file "' . $outputFile . '" for storing decrypted data.',
1975
$handler = new Crypt_GPG_DecryptStatusHandler($this->engine,
1976
$this->decryptKeys);
1978
$this->engine->reset();
1979
$this->engine->addStatusHandler(array($handler, 'handle'));
1980
$this->engine->setOperation('--decrypt');
1981
$this->engine->setInput($input);
1982
$this->engine->setOutput($output);
1983
$this->engine->run();
1989
if ($outputFile !== null) {
1993
// if there was any problem decrypting the data, the handler will
1994
// deal with it here.
1995
$handler->throwException();
1997
if ($outputFile === null) {
2008
* @param string $data the data to be signed.
2009
* @param boolean $isFile whether or not the data is a filename.
2010
* @param string $outputFile the name of the file in which the signed data
2011
* should be stored. If null, the signed data is
2012
* returned as a string.
2013
* @param boolean $mode the data signing mode to use. Should be one of
2014
* {@link Crypt_GPG::SIGN_MODE_NORMAL},
2015
* {@link Crypt_GPG::SIGN_MODE_CLEAR} or
2016
* {@link Crypt_GPG::SIGN_MODE_DETACHED}.
2017
* @param boolean $armor if true, ASCII armored data is returned;
2018
* otherwise, binary data is returned. This has
2019
* no effect if the mode
2020
* <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
2022
* @param boolean $textmode if true, line-breaks in signed data be
2023
* normalized. Use this option when signing
2024
* e-mail, or for greater compatibility between
2025
* systems with different line-break formats.
2026
* Defaults to false. This has no effect if the
2027
* mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
2028
* used as clear-signing always uses textmode.
2030
* @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
2031
* string containing the signed data (or the signature
2032
* data if a detached signature is requested) is
2035
* @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
2036
* See {@link Crypt_GPG::addSignKey()}.
2038
* @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
2039
* incorrect or if a required passphrase is not specified.
2041
* @throws Crypt_GPG_FileException if the output file is not writeable or
2042
* if the input file is not readable.
2044
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
2045
* Use the <kbd>debug</kbd> option and file a bug report if these
2048
private function _sign($data, $isFile, $outputFile, $mode, $armor,
2051
if (count($this->signKeys) === 0) {
2052
throw new Crypt_GPG_KeyNotFoundException(
2053
'No signing keys specified.');
2057
$input = @fopen($data, 'rb');
2058
if ($input === false) {
2059
throw new Crypt_GPG_FileException('Could not open input ' .
2060
'file "' . $data . '" for signing.', 0, $data);
2063
$input = strval($data);
2066
if ($outputFile === null) {
2069
$output = @fopen($outputFile, 'wb');
2070
if ($output === false) {
2074
throw new Crypt_GPG_FileException('Could not open output ' .
2075
'file "' . $outputFile . '" for storing signed ' .
2076
'data.', 0, $outputFile);
2081
case Crypt_GPG::SIGN_MODE_DETACHED:
2082
$operation = '--detach-sign';
2084
case Crypt_GPG::SIGN_MODE_CLEAR:
2085
$operation = '--clearsign';
2087
case Crypt_GPG::SIGN_MODE_NORMAL:
2089
$operation = '--sign';
2094
$arguments = array();
2097
$arguments[] = '--armor';
2100
$arguments[] = '--textmode';
2103
foreach ($this->signKeys as $key) {
2104
$arguments[] = '--local-user ' .
2105
escapeshellarg($key['fingerprint']);
2108
$this->engine->reset();
2109
$this->engine->addStatusHandler(array($this, 'handleSignStatus'));
2110
$this->engine->setInput($input);
2111
$this->engine->setOutput($output);
2112
$this->engine->setOperation($operation, $arguments);
2113
$this->engine->run();
2119
if ($outputFile !== null) {
2123
$code = $this->engine->getErrorCode();
2126
case Crypt_GPG::ERROR_NONE:
2128
case Crypt_GPG::ERROR_KEY_NOT_FOUND:
2129
throw new Crypt_GPG_KeyNotFoundException(
2130
'Cannot sign data. Private key not found. Import the '.
2131
'private key before trying to sign data.', $code);
2132
case Crypt_GPG::ERROR_BAD_PASSPHRASE:
2133
throw new Crypt_GPG_BadPassphraseException(
2134
'Cannot sign data. Incorrect passphrase provided.', $code);
2135
case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
2136
throw new Crypt_GPG_BadPassphraseException(
2137
'Cannot sign data. No passphrase provided.', $code);
2139
throw new Crypt_GPG_Exception(
2140
'Unknown error signing data. Please use the \'debug\' option ' .
2141
'when creating the Crypt_GPG object, and file a bug report ' .
2142
'at ' . self::BUG_URI, $code);
2145
if ($outputFile === null) {
2151
// {{{ _encryptAndSign()
2154
* Encrypts and signs data
2156
* @param string $data the data to be encrypted and signed.
2157
* @param boolean $isFile whether or not the data is a filename.
2158
* @param string $outputFile the name of the file in which the encrypted,
2159
* signed data should be stored. If null, the
2160
* encrypted, signed data is returned as a
2162
* @param boolean $armor if true, ASCII armored data is returned;
2163
* otherwise, binary data is returned.
2165
* @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
2166
* string containing the encrypted, signed data is
2169
* @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
2170
* or if no signing key is specified. See
2171
* {@link Crypt_GPG::addEncryptKey()} and
2172
* {@link Crypt_GPG::addSignKey()}.
2174
* @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
2175
* incorrect or if a required passphrase is not specified.
2177
* @throws Crypt_GPG_FileException if the output file is not writeable or
2178
* if the input file is not readable.
2180
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
2181
* Use the <kbd>debug</kbd> option and file a bug report if these
2184
private function _encryptAndSign($data, $isFile, $outputFile, $armor)
2186
if (count($this->signKeys) === 0) {
2187
throw new Crypt_GPG_KeyNotFoundException(
2188
'No signing keys specified.');
2191
if (count($this->encryptKeys) === 0) {
2192
throw new Crypt_GPG_KeyNotFoundException(
2193
'No encryption keys specified.');
2198
$input = @fopen($data, 'rb');
2199
if ($input === false) {
2200
throw new Crypt_GPG_FileException('Could not open input ' .
2201
'file "' . $data . '" for encrypting and signing.', 0,
2205
$input = strval($data);
2208
if ($outputFile === null) {
2211
$output = @fopen($outputFile, 'wb');
2212
if ($output === false) {
2216
throw new Crypt_GPG_FileException('Could not open output ' .
2217
'file "' . $outputFile . '" for storing encrypted, ' .
2218
'signed data.', 0, $outputFile);
2222
$arguments = ($armor) ? array('--armor') : array();
2224
foreach ($this->signKeys as $key) {
2225
$arguments[] = '--local-user ' .
2226
escapeshellarg($key['fingerprint']);
2229
foreach ($this->encryptKeys as $key) {
2230
$arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
2233
$this->engine->reset();
2234
$this->engine->addStatusHandler(array($this, 'handleSignStatus'));
2235
$this->engine->setInput($input);
2236
$this->engine->setOutput($output);
2237
$this->engine->setOperation('--encrypt --sign', $arguments);
2238
$this->engine->run();
2244
if ($outputFile !== null) {
2248
$code = $this->engine->getErrorCode();
2251
case Crypt_GPG::ERROR_NONE:
2253
case Crypt_GPG::ERROR_KEY_NOT_FOUND:
2254
throw new Crypt_GPG_KeyNotFoundException(
2255
'Cannot sign encrypted data. Private key not found. Import '.
2256
'the private key before trying to sign the encrypted data.',
2258
case Crypt_GPG::ERROR_BAD_PASSPHRASE:
2259
throw new Crypt_GPG_BadPassphraseException(
2260
'Cannot sign encrypted data. Incorrect passphrase provided.',
2262
case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
2263
throw new Crypt_GPG_BadPassphraseException(
2264
'Cannot sign encrypted data. No passphrase provided.', $code);
2266
throw new Crypt_GPG_Exception(
2267
'Unknown error encrypting and signing data. Please use the ' .
2268
'\'debug\' option when creating the Crypt_GPG object, and ' .
2269
'file a bug report at ' . self::BUG_URI, $code);
2272
if ($outputFile === null) {
2283
* @param string $data the signed data to be verified.
2284
* @param boolean $isFile whether or not the data is a filename.
2285
* @param string $signature if verifying a file signed using a detached
2286
* signature, this must be the detached signature
2287
* data. Otherwise, specify ''.
2289
* @return array an array of {@link Crypt_GPG_Signature} objects for the
2292
* @throws Crypt_GPG_NoDataException if the provided data is not signed
2295
* @throws Crypt_GPG_FileException if the input file is not readable.
2297
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
2298
* Use the <kbd>debug</kbd> option and file a bug report if these
2301
* @see Crypt_GPG_Signature
2303
private function _verify($data, $isFile, $signature)
2305
if ($signature == '') {
2306
$operation = '--verify';
2307
$arguments = array();
2309
// Signed data goes in FD_MESSAGE, detached signature data goes in
2311
$operation = '--verify - "-&' . Crypt_GPG_Engine::FD_MESSAGE. '"';
2312
$arguments = array('--enable-special-filenames');
2315
$handler = new Crypt_GPG_VerifyStatusHandler();
2318
$input = @fopen($data, 'rb');
2319
if ($input === false) {
2320
throw new Crypt_GPG_FileException('Could not open input ' .
2321
'file "' . $data . '" for verifying.', 0, $data);
2324
$input = strval($data);
2326
throw new Crypt_GPG_NoDataException(
2327
'No valid signature data found.', Crypt_GPG::ERROR_NO_DATA);
2331
$this->engine->reset();
2332
$this->engine->addStatusHandler(array($handler, 'handle'));
2334
if ($signature == '') {
2335
// signed or clearsigned data
2336
$this->engine->setInput($input);
2338
// detached signature
2339
$this->engine->setInput($signature);
2340
$this->engine->setMessage($input);
2343
$this->engine->setOperation($operation, $arguments);
2344
$this->engine->run();
2350
$code = $this->engine->getErrorCode();
2353
case Crypt_GPG::ERROR_NONE:
2354
case Crypt_GPG::ERROR_BAD_SIGNATURE:
2356
case Crypt_GPG::ERROR_NO_DATA:
2357
throw new Crypt_GPG_NoDataException(
2358
'No valid signature data found.', $code);
2359
case Crypt_GPG::ERROR_KEY_NOT_FOUND:
2360
throw new Crypt_GPG_KeyNotFoundException(
2361
'Public key required for data verification not in keyring.',
2364
throw new Crypt_GPG_Exception(
2365
'Unknown error validating signature details. Please use the ' .
2366
'\'debug\' option when creating the Crypt_GPG object, and ' .
2367
'file a bug report at ' . self::BUG_URI, $code);
2370
return $handler->getSignatures();
2374
// {{{ _decryptAndVerify()
2377
* Decrypts and verifies encrypted, signed data
2379
* @param string $data the encrypted signed data to be decrypted and
2381
* @param boolean $isFile whether or not the data is a filename.
2382
* @param string $outputFile the name of the file to which the decrypted
2383
* data should be written. If null, the decrypted
2384
* data is returned in the results array.
2386
* @return array two element array. The array has an element 'data'
2387
* containing the decrypted data and an element
2388
* 'signatures' containing an array of
2389
* {@link Crypt_GPG_Signature} objects for the signed data.
2390
* If the decrypted data is written to a file, the 'data'
2393
* @throws Crypt_GPG_KeyNotFoundException if the private key needed to
2394
* decrypt the data is not in the user's keyring or it the public
2395
* key needed for verification is not in the user's keyring.
2397
* @throws Crypt_GPG_NoDataException if specified data does not contain
2398
* GPG signed, encrypted data.
2400
* @throws Crypt_GPG_BadPassphraseException if a required passphrase is
2401
* incorrect or if a required passphrase is not specified. See
2402
* {@link Crypt_GPG::addDecryptKey()}.
2404
* @throws Crypt_GPG_FileException if the output file is not writeable or
2405
* if the input file is not readable.
2407
* @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
2408
* Use the <kbd>debug</kbd> option and file a bug report if these
2411
* @see Crypt_GPG_Signature
2413
private function _decryptAndVerify($data, $isFile, $outputFile)
2416
$input = @fopen($data, 'rb');
2417
if ($input === false) {
2418
throw new Crypt_GPG_FileException('Could not open input ' .
2419
'file "' . $data . '" for decrypting and verifying.', 0,
2423
$input = strval($data);
2425
throw new Crypt_GPG_NoDataException(
2426
'No valid encrypted signed data found.',
2427
Crypt_GPG::ERROR_NO_DATA);
2431
if ($outputFile === null) {
2434
$output = @fopen($outputFile, 'wb');
2435
if ($output === false) {
2439
throw new Crypt_GPG_FileException('Could not open output ' .
2440
'file "' . $outputFile . '" for storing decrypted data.',
2445
$verifyHandler = new Crypt_GPG_VerifyStatusHandler();
2447
$decryptHandler = new Crypt_GPG_DecryptStatusHandler($this->engine,
2448
$this->decryptKeys);
2450
$this->engine->reset();
2451
$this->engine->addStatusHandler(array($verifyHandler, 'handle'));
2452
$this->engine->addStatusHandler(array($decryptHandler, 'handle'));
2453
$this->engine->setInput($input);
2454
$this->engine->setOutput($output);
2455
$this->engine->setOperation('--decrypt');
2456
$this->engine->run();
2462
if ($outputFile !== null) {
2468
'signatures' => $verifyHandler->getSignatures()
2471
// if there was any problem decrypting the data, the handler will
2472
// deal with it here.
2474
$decryptHandler->throwException();
2475
} catch (Exception $e) {
2476
if ($e instanceof Crypt_GPG_KeyNotFoundException) {
2477
throw new Crypt_GPG_KeyNotFoundException(
2478
'Public key required for data verification not in ',
2479
'the keyring. Either no suitable private decryption key ' .
2480
'is in the keyring or the public key required for data ' .
2481
'verification is not in the keyring. Import a suitable ' .
2482
'key before trying to decrypt and verify this data.',
2483
self::ERROR_KEY_NOT_FOUND);
2486
if ($e instanceof Crypt_GPG_NoDataException) {
2487
throw new Crypt_GPG_NoDataException(
2488
'Cannot decrypt and verify data. No PGP encrypted data ' .
2489
'was found in the provided data.', self::ERROR_NO_DATA);
2495
if ($outputFile === null) {
2496
$return['data'] = $output;