From a98a4f8bb56eacffff1765ff09dd29af26e5fc12 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Wed, 27 Aug 2014 17:45:21 +0200 Subject: Remove 3rd party libs from our repository and define the dependencies in composer.json-dist. Also remove the ancient utf8 lib and replace it with 'Patchwork UTF-8 for PHP'. For direct git checkouts, copy composer.json-dist into composer.json and run `php composer.phar install` to install the dependencies. --- program/lib/Crypt/GPG.php | 2386 -------------------- program/lib/Crypt/GPG/ByteUtils.php | 105 - program/lib/Crypt/GPG/DecryptStatusHandler.php | 344 --- program/lib/Crypt/GPG/Engine.php | 2006 ---------------- program/lib/Crypt/GPG/Exceptions.php | 598 ----- program/lib/Crypt/GPG/Key.php | 223 -- program/lib/Crypt/GPG/KeyGenerator.php | 790 ------- program/lib/Crypt/GPG/KeyGeneratorErrorHandler.php | 121 - .../lib/Crypt/GPG/KeyGeneratorStatusHandler.php | 173 -- program/lib/Crypt/GPG/PinEntry.php | 875 ------- program/lib/Crypt/GPG/ProcessControl.php | 150 -- program/lib/Crypt/GPG/Signature.php | 427 ---- program/lib/Crypt/GPG/SubKey.php | 672 ------ program/lib/Crypt/GPG/UserId.php | 373 --- program/lib/Crypt/GPG/VerifyStatusHandler.php | 216 -- program/lib/Crypt/GPGAbstract.php | 508 ----- 16 files changed, 9967 deletions(-) delete mode 100644 program/lib/Crypt/GPG.php delete mode 100644 program/lib/Crypt/GPG/ByteUtils.php delete mode 100644 program/lib/Crypt/GPG/DecryptStatusHandler.php delete mode 100644 program/lib/Crypt/GPG/Engine.php delete mode 100644 program/lib/Crypt/GPG/Exceptions.php delete mode 100644 program/lib/Crypt/GPG/Key.php delete mode 100644 program/lib/Crypt/GPG/KeyGenerator.php delete mode 100644 program/lib/Crypt/GPG/KeyGeneratorErrorHandler.php delete mode 100644 program/lib/Crypt/GPG/KeyGeneratorStatusHandler.php delete mode 100644 program/lib/Crypt/GPG/PinEntry.php delete mode 100644 program/lib/Crypt/GPG/ProcessControl.php delete mode 100644 program/lib/Crypt/GPG/Signature.php delete mode 100644 program/lib/Crypt/GPG/SubKey.php delete mode 100644 program/lib/Crypt/GPG/UserId.php delete mode 100644 program/lib/Crypt/GPG/VerifyStatusHandler.php delete mode 100644 program/lib/Crypt/GPGAbstract.php (limited to 'program/lib/Crypt') diff --git a/program/lib/Crypt/GPG.php b/program/lib/Crypt/GPG.php deleted file mode 100644 index 5c2231289..000000000 --- a/program/lib/Crypt/GPG.php +++ /dev/null @@ -1,2386 +0,0 @@ - - * addEncryptKey($mySecretKeyId); - * $encryptedData = $gpg->encrypt($data); - * ?> - * - * - * PHP version 5 - * - * LICENSE: - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * @category Encryption - * @package Crypt_GPG - * @author Nathan Fredrickson - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://pear.php.net/manual/en/package.encryption.crypt-gpg.php - * @link http://www.gnupg.org/ - */ - -/** - * Base class for GPG methods - */ -require_once 'Crypt/GPGAbstract.php'; - -/** - * Signature handler class - */ -require_once 'Crypt/GPG/VerifyStatusHandler.php'; - -/** - * Decryption handler class - */ -require_once 'Crypt/GPG/DecryptStatusHandler.php'; - -// {{{ class Crypt_GPG - -/** - * A class to use GPG from PHP - * - * This class provides an object oriented interface to GNU Privacy Guard (GPG). - * - * Though GPG can support symmetric-key cryptography, this class is intended - * only to facilitate public-key cryptography. - * - * @category Encryption - * @package Crypt_GPG - * @author Nathan Fredrickson - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -class Crypt_GPG extends Crypt_GPGAbstract -{ - // {{{ class constants for data signing modes - - /** - * Signing mode for normal signing of data. The signed message will not - * be readable without special software. - * - * This is the default signing mode. - * - * @see Crypt_GPG::sign() - * @see Crypt_GPG::signFile() - */ - const SIGN_MODE_NORMAL = 1; - - /** - * Signing mode for clearsigning data. Clearsigned signatures are ASCII - * armored data and are readable without special software. If the signed - * message is unencrypted, the message will still be readable. The message - * text will be in the original encoding. - * - * @see Crypt_GPG::sign() - * @see Crypt_GPG::signFile() - */ - const SIGN_MODE_CLEAR = 2; - - /** - * Signing mode for creating a detached signature. When using detached - * signatures, only the signature data is returned. The original message - * text may be distributed separately from the signature data. This is - * useful for miltipart/signed email messages as per - * {@link http://www.ietf.org/rfc/rfc3156.txt RFC 3156}. - * - * @see Crypt_GPG::sign() - * @see Crypt_GPG::signFile() - */ - const SIGN_MODE_DETACHED = 3; - - // }}} - // {{{ class constants for fingerprint formats - - /** - * No formatting is performed. - * - * Example: C3BC615AD9C766E5A85C1F2716D27458B1BBA1C4 - * - * @see Crypt_GPG::getFingerprint() - */ - const FORMAT_NONE = 1; - - /** - * Fingerprint is formatted in the format used by the GnuPG gpg command's - * default output. - * - * Example: C3BC 615A D9C7 66E5 A85C 1F27 16D2 7458 B1BB A1C4 - * - * @see Crypt_GPG::getFingerprint() - */ - const FORMAT_CANONICAL = 2; - - /** - * Fingerprint is formatted in the format used when displaying X.509 - * certificates - * - * Example: C3:BC:61:5A:D9:C7:66:E5:A8:5C:1F:27:16:D2:74:58:B1:BB:A1:C4 - * - * @see Crypt_GPG::getFingerprint() - */ - const FORMAT_X509 = 3; - - // }}} - // {{{ class constants for boolean options - - /** - * Use to specify ASCII armored mode for returned data - */ - const ARMOR_ASCII = true; - - /** - * Use to specify binary mode for returned data - */ - const ARMOR_BINARY = false; - - /** - * Use to specify that line breaks in signed text should be normalized - */ - const TEXT_NORMALIZED = true; - - /** - * Use to specify that line breaks in signed text should not be normalized - */ - const TEXT_RAW = false; - - // }}} - // {{{ protected class properties - - /** - * Engine used to control the GPG subprocess - * - * @var Crypt_GPG_Engine - * - * @see Crypt_GPG::setEngine() - */ - protected $engine = null; - - /** - * Keys used to encrypt - * - * The array is of the form: - * - * array( - * $key_id => array( - * 'fingerprint' => $fingerprint, - * 'passphrase' => null - * ) - * ); - * - * - * @var array - * @see Crypt_GPG::addEncryptKey() - * @see Crypt_GPG::clearEncryptKeys() - */ - protected $encryptKeys = array(); - - /** - * Keys used to decrypt - * - * The array is of the form: - * - * array( - * $key_id => array( - * 'fingerprint' => $fingerprint, - * 'passphrase' => $passphrase - * ) - * ); - * - * - * @var array - * @see Crypt_GPG::addSignKey() - * @see Crypt_GPG::clearSignKeys() - */ - protected $signKeys = array(); - - /** - * Keys used to sign - * - * The array is of the form: - * - * array( - * $key_id => array( - * 'fingerprint' => $fingerprint, - * 'passphrase' => $passphrase - * ) - * ); - * - * - * @var array - * @see Crypt_GPG::addDecryptKey() - * @see Crypt_GPG::clearDecryptKeys() - */ - protected $decryptKeys = array(); - - // }}} - // {{{ importKey() - - /** - * Imports a public or private key into the keyring - * - * Keys may be removed from the keyring using - * {@link Crypt_GPG::deletePublicKey()} or - * {@link Crypt_GPG::deletePrivateKey()}. - * - * @param string $data the key data to be imported. - * - * @return array an associative array containing the following elements: - * - fingerprint - the fingerprint of the - * imported key, - * - public_imported - the number of public - * keys imported, - * - public_unchanged - the number of unchanged - * public keys, - * - private_imported - the number of private - * keys imported, - * - private_unchanged - the number of unchanged - * private keys. - * - * @throws Crypt_GPG_NoDataException if the key data is missing or if the - * data is is not valid key data. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function importKey($data) - { - return $this->_importKey($data, false); - } - - // }}} - // {{{ importKeyFile() - - /** - * Imports a public or private key file into the keyring - * - * Keys may be removed from the keyring using - * {@link Crypt_GPG::deletePublicKey()} or - * {@link Crypt_GPG::deletePrivateKey()}. - * - * @param string $filename the key file to be imported. - * - * @return array an associative array containing the following elements: - * - fingerprint - the fingerprint of the - * imported key, - * - public_imported - the number of public - * keys imported, - * - public_unchanged - the number of unchanged - * public keys, - * - private_imported - the number of private - * keys imported, - * - private_unchanged - the number of unchanged - * private keys. - * private keys. - * - * @throws Crypt_GPG_NoDataException if the key data is missing or if the - * data is is not valid key data. - * - * @throws Crypt_GPG_FileException if the key file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function importKeyFile($filename) - { - return $this->_importKey($filename, true); - } - - // }}} - // {{{ exportPublicKey() - - /** - * Exports a public key from the keyring - * - * The exported key remains on the keyring. To delete the public key, use - * {@link Crypt_GPG::deletePublicKey()}. - * - * If more than one key fingerprint is available for the specified - * $keyId (for example, if you use a non-unique uid) only the - * first public key is exported. - * - * @param string $keyId either the full uid of the public key, the email - * part of the uid of the public key or the key id of - * the public key. For example, - * "Test User (example) ", - * "test@example.com" or a hexadecimal string. - * @param boolean $armor optional. If true, ASCII armored data is returned; - * otherwise, binary data is returned. Defaults to - * true. - * - * @return string the public key data. - * - * @throws Crypt_GPG_KeyNotFoundException if a public key with the given - * $keyId is not found. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function exportPublicKey($keyId, $armor = true) - { - $fingerprint = $this->getFingerprint($keyId); - - if ($fingerprint === null) { - throw new Crypt_GPG_KeyNotFoundException( - 'Public key not found: ' . $keyId, - self::ERROR_KEY_NOT_FOUND, - $keyId - ); - } - - $keyData = ''; - $operation = '--export ' . escapeshellarg($fingerprint); - $arguments = ($armor) ? array('--armor') : array(); - - $this->engine->reset(); - $this->engine->setOutput($keyData); - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - $code = $this->engine->getErrorCode(); - - if ($code !== self::ERROR_NONE) { - throw new Crypt_GPG_Exception( - 'Unknown error exporting public key. Please use the ' . - '\'debug\' option when creating the Crypt_GPG object, and ' . - 'file a bug report at ' . self::BUG_URI, - $code - ); - } - - return $keyData; - } - - // }}} - // {{{ deletePublicKey() - - /** - * Deletes a public key from the keyring - * - * If more than one key fingerprint is available for the specified - * $keyId (for example, if you use a non-unique uid) only the - * first public key is deleted. - * - * The private key must be deleted first or an exception will be thrown. - * See {@link Crypt_GPG::deletePrivateKey()}. - * - * @param string $keyId either the full uid of the public key, the email - * part of the uid of the public key or the key id of - * the public key. For example, - * "Test User (example) ", - * "test@example.com" or a hexadecimal string. - * - * @return void - * - * @throws Crypt_GPG_KeyNotFoundException if a public key with the given - * $keyId is not found. - * - * @throws Crypt_GPG_DeletePrivateKeyException if the specified public key - * has an associated private key on the keyring. The private key - * must be deleted first. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function deletePublicKey($keyId) - { - $fingerprint = $this->getFingerprint($keyId); - - if ($fingerprint === null) { - throw new Crypt_GPG_KeyNotFoundException( - 'Public key not found: ' . $keyId, - self::ERROR_KEY_NOT_FOUND, - $keyId - ); - } - - $operation = '--delete-key ' . escapeshellarg($fingerprint); - $arguments = array( - '--batch', - '--yes' - ); - - $this->engine->reset(); - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - break; - case self::ERROR_DELETE_PRIVATE_KEY: - throw new Crypt_GPG_DeletePrivateKeyException( - 'Private key must be deleted before public key can be ' . - 'deleted.', - $code, - $keyId - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error deleting public key. Please use the ' . - '\'debug\' option when creating the Crypt_GPG object, and ' . - 'file a bug report at ' . self::BUG_URI, - $code - ); - } - } - - // }}} - // {{{ deletePrivateKey() - - /** - * Deletes a private key from the keyring - * - * If more than one key fingerprint is available for the specified - * $keyId (for example, if you use a non-unique uid) only the - * first private key is deleted. - * - * Calls GPG with the --delete-secret-key command. - * - * @param string $keyId either the full uid of the private key, the email - * part of the uid of the private key or the key id of - * the private key. For example, - * "Test User (example) ", - * "test@example.com" or a hexadecimal string. - * - * @return void - * - * @throws Crypt_GPG_KeyNotFoundException if a private key with the given - * $keyId is not found. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function deletePrivateKey($keyId) - { - $fingerprint = $this->getFingerprint($keyId); - - if ($fingerprint === null) { - throw new Crypt_GPG_KeyNotFoundException( - 'Private key not found: ' . $keyId, - self::ERROR_KEY_NOT_FOUND, - $keyId - ); - } - - $operation = '--delete-secret-key ' . escapeshellarg($fingerprint); - $arguments = array( - '--batch', - '--yes' - ); - - $this->engine->reset(); - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - break; - case self::ERROR_KEY_NOT_FOUND: - throw new Crypt_GPG_KeyNotFoundException( - 'Private key not found: ' . $keyId, - $code, - $keyId - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error deleting private key. Please use the ' . - '\'debug\' option when creating the Crypt_GPG object, and ' . - 'file a bug report at ' . self::BUG_URI, - $code - ); - } - } - - // }}} - // {{{ getKeys() - - /** - * Gets the available keys in the keyring - * - * Calls GPG with the --list-keys command and grabs keys. See - * the first section of doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG package} for a detailed - * description of how the GPG command output is parsed. - * - * @param string $keyId optional. Only keys with that match the specified - * pattern are returned. The pattern may be part of - * a user id, a key id or a key fingerprint. If not - * specified, all keys are returned. - * - * @return array an array of {@link Crypt_GPG_Key} objects. If no keys - * match the specified $keyId an empty array is - * returned. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG_Key - */ - public function getKeys($keyId = '') - { - return parent::_getKeys($keyId); - } - - // }}} - // {{{ getFingerprint() - - /** - * Gets a key fingerprint from the keyring - * - * If more than one key fingerprint is available (for example, if you use - * a non-unique user id) only the first key fingerprint is returned. - * - * Calls the GPG --list-keys command with the - * --with-fingerprint option to retrieve a public key - * fingerprint. - * - * @param string $keyId either the full user id of the key, the email - * part of the user id of the key, or the key id of - * the key. For example, - * "Test User (example) ", - * "test@example.com" or a hexadecimal string. - * @param integer $format optional. How the fingerprint should be formatted. - * Use {@link Crypt_GPG::FORMAT_X509} for X.509 - * certificate format, - * {@link Crypt_GPG::FORMAT_CANONICAL} for the format - * used by GnuPG output and - * {@link Crypt_GPG::FORMAT_NONE} for no formatting. - * Defaults to Crypt_GPG::FORMAT_NONE. - * - * @return string the fingerprint of the key, or null if no fingerprint - * is found for the given $keyId. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function getFingerprint($keyId, $format = self::FORMAT_NONE) - { - $output = ''; - $operation = '--list-keys ' . escapeshellarg($keyId); - $arguments = array( - '--with-colons', - '--with-fingerprint' - ); - - $this->engine->reset(); - $this->engine->setOutput($output); - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - case self::ERROR_KEY_NOT_FOUND: - // ignore not found key errors - break; - default: - throw new Crypt_GPG_Exception( - 'Unknown error getting key fingerprint. Please use the ' . - '\'debug\' option when creating the Crypt_GPG object, and ' . - 'file a bug report at ' . self::BUG_URI, - $code - ); - } - - $fingerprint = null; - - $lines = explode(PHP_EOL, $output); - foreach ($lines as $line) { - if (substr($line, 0, 3) == 'fpr') { - $lineExp = explode(':', $line); - $fingerprint = $lineExp[9]; - - switch ($format) { - case self::FORMAT_CANONICAL: - $fingerprintExp = str_split($fingerprint, 4); - $format = '%s %s %s %s %s %s %s %s %s %s'; - $fingerprint = vsprintf($format, $fingerprintExp); - break; - - case self::FORMAT_X509: - $fingerprintExp = str_split($fingerprint, 2); - $fingerprint = implode(':', $fingerprintExp); - break; - } - - break; - } - } - - return $fingerprint; - } - - // }}} - // {{{ encrypt() - - /** - * Encrypts string data - * - * Data is ASCII armored by default but may optionally be returned as - * binary. - * - * @param string $data the data to be encrypted. - * @param boolean $armor optional. If true, ASCII armored data is returned; - * otherwise, binary data is returned. Defaults to - * true. - * - * @return string the encrypted data. - * - * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified. - * See {@link Crypt_GPG::addEncryptKey()}. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @sensitive $data - */ - public function encrypt($data, $armor = self::ARMOR_ASCII) - { - return $this->_encrypt($data, false, null, $armor); - } - - // }}} - // {{{ encryptFile() - - /** - * Encrypts a file - * - * Encrypted data is ASCII armored by default but may optionally be saved - * as binary. - * - * @param string $filename the filename of the file to encrypt. - * @param string $encryptedFile optional. The filename of the file in - * which to store the encrypted data. If null - * or unspecified, the encrypted data is - * returned as a string. - * @param boolean $armor optional. If true, ASCII armored data is - * returned; otherwise, binary data is - * returned. Defaults to true. - * - * @return void|string if the $encryptedFile parameter is null, - * a string containing the encrypted data is returned. - * - * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified. - * See {@link Crypt_GPG::addEncryptKey()}. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function encryptFile( - $filename, - $encryptedFile = null, - $armor = self::ARMOR_ASCII - ) { - return $this->_encrypt($filename, true, $encryptedFile, $armor); - } - - // }}} - // {{{ encryptAndSign() - - /** - * Encrypts and signs data - * - * Data is encrypted and signed in a single pass. - * - * NOTE: Until GnuPG version 1.4.10, it was not possible to verify - * encrypted-signed data without decrypting it at the same time. If you try - * to use {@link Crypt_GPG::verify()} method on encrypted-signed data with - * earlier GnuPG versions, you will get an error. Please use - * {@link Crypt_GPG::decryptAndVerify()} to verify encrypted-signed data. - * - * @param string $data the data to be encrypted and signed. - * @param boolean $armor optional. If true, ASCII armored data is returned; - * otherwise, binary data is returned. Defaults to - * true. - * - * @return string the encrypted signed data. - * - * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified - * or if no signing key is specified. See - * {@link Crypt_GPG::addEncryptKey()} and - * {@link Crypt_GPG::addSignKey()}. - * - * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is - * incorrect or if a required passphrase is not specified. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG::decryptAndVerify() - */ - public function encryptAndSign($data, $armor = self::ARMOR_ASCII) - { - return $this->_encryptAndSign($data, false, null, $armor); - } - - // }}} - // {{{ encryptAndSignFile() - - /** - * Encrypts and signs a file - * - * The file is encrypted and signed in a single pass. - * - * NOTE: Until GnuPG version 1.4.10, it was not possible to verify - * encrypted-signed files without decrypting them at the same time. If you - * try to use {@link Crypt_GPG::verify()} method on encrypted-signed files - * with earlier GnuPG versions, you will get an error. Please use - * {@link Crypt_GPG::decryptAndVerifyFile()} to verify encrypted-signed - * files. - * - * @param string $filename the name of the file containing the data to - * be encrypted and signed. - * @param string $signedFile optional. The name of the file in which the - * encrypted, signed data should be stored. If - * null or unspecified, the encrypted, signed - * data is returned as a string. - * @param boolean $armor optional. If true, ASCII armored data is - * returned; otherwise, binary data is returned. - * Defaults to true. - * - * @return void|string if the $signedFile parameter is null, a - * string containing the encrypted, signed data is - * returned. - * - * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified - * or if no signing key is specified. See - * {@link Crypt_GPG::addEncryptKey()} and - * {@link Crypt_GPG::addSignKey()}. - * - * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is - * incorrect or if a required passphrase is not specified. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG::decryptAndVerifyFile() - */ - public function encryptAndSignFile( - $filename, - $signedFile = null, - $armor = self::ARMOR_ASCII - ) { - return $this->_encryptAndSign($filename, true, $signedFile, $armor); - } - - // }}} - // {{{ decrypt() - - /** - * Decrypts string data - * - * This method assumes the required private key is available in the keyring - * and throws an exception if the private key is not available. To add a - * private key to the keyring, use the {@link Crypt_GPG::importKey()} or - * {@link Crypt_GPG::importKeyFile()} methods. - * - * @param string $encryptedData the data to be decrypted. - * - * @return string the decrypted data. - * - * @throws Crypt_GPG_KeyNotFoundException if the private key needed to - * decrypt the data is not in the user's keyring. - * - * @throws Crypt_GPG_NoDataException if specified data does not contain - * GPG encrypted data. - * - * @throws Crypt_GPG_BadPassphraseException if a required passphrase is - * incorrect or if a required passphrase is not specified. See - * {@link Crypt_GPG::addDecryptKey()}. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function decrypt($encryptedData) - { - return $this->_decrypt($encryptedData, false, null); - } - - // }}} - // {{{ decryptFile() - - /** - * Decrypts a file - * - * This method assumes the required private key is available in the keyring - * and throws an exception if the private key is not available. To add a - * private key to the keyring, use the {@link Crypt_GPG::importKey()} or - * {@link Crypt_GPG::importKeyFile()} methods. - * - * @param string $encryptedFile the name of the encrypted file data to - * decrypt. - * @param string $decryptedFile optional. The name of the file to which the - * decrypted data should be written. If null - * or unspecified, the decrypted data is - * returned as a string. - * - * @return void|string if the $decryptedFile parameter is null, - * a string containing the decrypted data is returned. - * - * @throws Crypt_GPG_KeyNotFoundException if the private key needed to - * decrypt the data is not in the user's keyring. - * - * @throws Crypt_GPG_NoDataException if specified data does not contain - * GPG encrypted data. - * - * @throws Crypt_GPG_BadPassphraseException if a required passphrase is - * incorrect or if a required passphrase is not specified. See - * {@link Crypt_GPG::addDecryptKey()}. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function decryptFile($encryptedFile, $decryptedFile = null) - { - return $this->_decrypt($encryptedFile, true, $decryptedFile); - } - - // }}} - // {{{ decryptAndVerify() - - /** - * Decrypts and verifies string data - * - * This method assumes the required private key is available in the keyring - * and throws an exception if the private key is not available. To add a - * private key to the keyring, use the {@link Crypt_GPG::importKey()} or - * {@link Crypt_GPG::importKeyFile()} methods. - * - * @param string $encryptedData the encrypted, signed data to be decrypted - * and verified. - * - * @return array two element array. The array has an element 'data' - * containing the decrypted data and an element - * 'signatures' containing an array of - * {@link Crypt_GPG_Signature} objects for the signed data. - * - * @throws Crypt_GPG_KeyNotFoundException if the private key needed to - * decrypt the data is not in the user's keyring. - * - * @throws Crypt_GPG_NoDataException if specified data does not contain - * GPG encrypted data. - * - * @throws Crypt_GPG_BadPassphraseException if a required passphrase is - * incorrect or if a required passphrase is not specified. See - * {@link Crypt_GPG::addDecryptKey()}. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function decryptAndVerify($encryptedData) - { - return $this->_decryptAndVerify($encryptedData, false, null); - } - - // }}} - // {{{ decryptAndVerifyFile() - - /** - * Decrypts and verifies a signed, encrypted file - * - * This method assumes the required private key is available in the keyring - * and throws an exception if the private key is not available. To add a - * private key to the keyring, use the {@link Crypt_GPG::importKey()} or - * {@link Crypt_GPG::importKeyFile()} methods. - * - * @param string $encryptedFile the name of the signed, encrypted file to - * to decrypt and verify. - * @param string $decryptedFile optional. The name of the file to which the - * decrypted data should be written. If null - * or unspecified, the decrypted data is - * returned in the results array. - * - * @return array two element array. The array has an element 'data' - * containing the decrypted data and an element - * 'signatures' containing an array of - * {@link Crypt_GPG_Signature} objects for the signed data. - * If the decrypted data is written to a file, the 'data' - * element is null. - * - * @throws Crypt_GPG_KeyNotFoundException if the private key needed to - * decrypt the data is not in the user's keyring. - * - * @throws Crypt_GPG_NoDataException if specified data does not contain - * GPG encrypted data. - * - * @throws Crypt_GPG_BadPassphraseException if a required passphrase is - * incorrect or if a required passphrase is not specified. See - * {@link Crypt_GPG::addDecryptKey()}. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function decryptAndVerifyFile($encryptedFile, $decryptedFile = null) - { - return $this->_decryptAndVerify($encryptedFile, true, $decryptedFile); - } - - // }}} - // {{{ sign() - - /** - * Signs data - * - * Data may be signed using any one of the three available signing modes: - * - {@link Crypt_GPG::SIGN_MODE_NORMAL} - * - {@link Crypt_GPG::SIGN_MODE_CLEAR} - * - {@link Crypt_GPG::SIGN_MODE_DETACHED} - * - * @param string $data the data to be signed. - * @param boolean $mode optional. The data signing mode to use. Should - * be one of {@link Crypt_GPG::SIGN_MODE_NORMAL}, - * {@link Crypt_GPG::SIGN_MODE_CLEAR} or - * {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not - * specified, defaults to - * Crypt_GPG::SIGN_MODE_NORMAL. - * @param boolean $armor optional. If true, ASCII armored data is - * returned; otherwise, binary data is returned. - * Defaults to true. This has no effect if the - * mode Crypt_GPG::SIGN_MODE_CLEAR is - * used. - * @param boolean $textmode optional. If true, line-breaks in signed data - * are normalized. Use this option when signing - * e-mail, or for greater compatibility between - * systems with different line-break formats. - * Defaults to false. This has no effect if the - * mode Crypt_GPG::SIGN_MODE_CLEAR is - * used as clear-signing always uses textmode. - * - * @return string the signed data, or the signature data if a detached - * signature is requested. - * - * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified. - * See {@link Crypt_GPG::addSignKey()}. - * - * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is - * incorrect or if a required passphrase is not specified. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function sign( - $data, - $mode = self::SIGN_MODE_NORMAL, - $armor = self::ARMOR_ASCII, - $textmode = self::TEXT_RAW - ) { - return $this->_sign($data, false, null, $mode, $armor, $textmode); - } - - // }}} - // {{{ signFile() - - /** - * Signs a file - * - * The file may be signed using any one of the three available signing - * modes: - * - {@link Crypt_GPG::SIGN_MODE_NORMAL} - * - {@link Crypt_GPG::SIGN_MODE_CLEAR} - * - {@link Crypt_GPG::SIGN_MODE_DETACHED} - * - * @param string $filename the name of the file containing the data to - * be signed. - * @param string $signedFile optional. The name of the file in which the - * signed data should be stored. If null or - * unspecified, the signed data is returned as a - * string. - * @param boolean $mode optional. The data signing mode to use. Should - * be one of {@link Crypt_GPG::SIGN_MODE_NORMAL}, - * {@link Crypt_GPG::SIGN_MODE_CLEAR} or - * {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not - * specified, defaults to - * Crypt_GPG::SIGN_MODE_NORMAL. - * @param boolean $armor optional. If true, ASCII armored data is - * returned; otherwise, binary data is returned. - * Defaults to true. This has no effect if the - * mode Crypt_GPG::SIGN_MODE_CLEAR is - * used. - * @param boolean $textmode optional. If true, line-breaks in signed data - * are normalized. Use this option when signing - * e-mail, or for greater compatibility between - * systems with different line-break formats. - * Defaults to false. This has no effect if the - * mode Crypt_GPG::SIGN_MODE_CLEAR is - * used as clear-signing always uses textmode. - * - * @return void|string if the $signedFile parameter is null, a - * string containing the signed data (or the signature - * data if a detached signature is requested) is - * returned. - * - * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified. - * See {@link Crypt_GPG::addSignKey()}. - * - * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is - * incorrect or if a required passphrase is not specified. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function signFile( - $filename, - $signedFile = null, - $mode = self::SIGN_MODE_NORMAL, - $armor = self::ARMOR_ASCII, - $textmode = self::TEXT_RAW - ) { - return $this->_sign( - $filename, - true, - $signedFile, - $mode, - $armor, - $textmode - ); - } - - // }}} - // {{{ verify() - - /** - * Verifies signed data - * - * The {@link Crypt_GPG::decrypt()} method may be used to get the original - * message if the signed data is not clearsigned and does not use a - * detached signature. - * - * @param string $signedData the signed data to be verified. - * @param string $signature optional. If verifying data signed using a - * detached signature, this must be the detached - * signature data. The data that was signed is - * specified in $signedData. - * - * @return array an array of {@link Crypt_GPG_Signature} objects for the - * signed data. For each signature that is valid, the - * {@link Crypt_GPG_Signature::isValid()} will return true. - * - * @throws Crypt_GPG_NoDataException if the provided data is not signed - * data. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG_Signature - */ - public function verify($signedData, $signature = '') - { - return $this->_verify($signedData, false, $signature); - } - - // }}} - // {{{ verifyFile() - - /** - * Verifies a signed file - * - * The {@link Crypt_GPG::decryptFile()} method may be used to get the - * original message if the signed data is not clearsigned and does not use - * a detached signature. - * - * @param string $filename the signed file to be verified. - * @param string $signature optional. If verifying a file signed using a - * detached signature, this must be the detached - * signature data. The file that was signed is - * specified in $filename. - * - * @return array an array of {@link Crypt_GPG_Signature} objects for the - * signed data. For each signature that is valid, the - * {@link Crypt_GPG_Signature::isValid()} will return true. - * - * @throws Crypt_GPG_NoDataException if the provided data is not signed - * data. - * - * @throws Crypt_GPG_FileException if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG_Signature - */ - public function verifyFile($filename, $signature = '') - { - return $this->_verify($filename, true, $signature); - } - - // }}} - // {{{ addDecryptKey() - - /** - * Adds a key to use for decryption - * - * @param mixed $key the key to use. This may be a key identifier, - * user id, fingerprint, {@link Crypt_GPG_Key} or - * {@link Crypt_GPG_SubKey}. The key must be able - * to encrypt. - * @param string $passphrase optional. The passphrase of the key required - * for decryption. - * - * @return Crypt_GPG the current object, for fluent interface. - * - * @see Crypt_GPG::decrypt() - * @see Crypt_GPG::decryptFile() - * @see Crypt_GPG::clearDecryptKeys() - * @see Crypt_GPG::_addKey() - * @see Crypt_GPG_DecryptStatusHandler - * - * @sensitive $passphrase - */ - public function addDecryptKey($key, $passphrase = null) - { - $this->_addKey($this->decryptKeys, true, false, $key, $passphrase); - return $this; - } - - // }}} - // {{{ addEncryptKey() - - /** - * Adds a key to use for encryption - * - * @param mixed $key the key to use. This may be a key identifier, user id - * user id, fingerprint, {@link Crypt_GPG_Key} or - * {@link Crypt_GPG_SubKey}. The key must be able to - * encrypt. - * - * @return Crypt_GPG the current object, for fluent interface. - * - * @see Crypt_GPG::encrypt() - * @see Crypt_GPG::encryptFile() - * @see Crypt_GPG::clearEncryptKeys() - * @see Crypt_GPG::_addKey() - */ - public function addEncryptKey($key) - { - $this->_addKey($this->encryptKeys, true, false, $key); - return $this; - } - - // }}} - // {{{ addSignKey() - - /** - * Adds a key to use for signing - * - * @param mixed $key the key to use. This may be a key identifier, - * user id, fingerprint, {@link Crypt_GPG_Key} or - * {@link Crypt_GPG_SubKey}. The key must be able - * to sign. - * @param string $passphrase optional. The passphrase of the key required - * for signing. - * - * @return Crypt_GPG the current object, for fluent interface. - * - * @see Crypt_GPG::sign() - * @see Crypt_GPG::signFile() - * @see Crypt_GPG::clearSignKeys() - * @see Crypt_GPG::handleSignStatus() - * @see Crypt_GPG::_addKey() - * - * @sensitive $passphrase - */ - public function addSignKey($key, $passphrase = null) - { - $this->_addKey($this->signKeys, false, true, $key, $passphrase); - return $this; - } - - // }}} - // {{{ clearDecryptKeys() - - /** - * Clears all decryption keys - * - * @return Crypt_GPG the current object, for fluent interface. - * - * @see Crypt_GPG::decrypt() - * @see Crypt_GPG::addDecryptKey() - */ - public function clearDecryptKeys() - { - $this->decryptKeys = array(); - return $this; - } - - // }}} - // {{{ clearEncryptKeys() - - /** - * Clears all encryption keys - * - * @return Crypt_GPG the current object, for fluent interface. - * - * @see Crypt_GPG::encrypt() - * @see Crypt_GPG::addEncryptKey() - */ - public function clearEncryptKeys() - { - $this->encryptKeys = array(); - return $this; - } - - // }}} - // {{{ clearSignKeys() - - /** - * Clears all signing keys - * - * @return Crypt_GPG the current object, for fluent interface. - * - * @see Crypt_GPG::sign() - * @see Crypt_GPG::addSignKey() - */ - public function clearSignKeys() - { - $this->signKeys = array(); - return $this; - } - - // }}} - // {{{ handleSignStatus() - - /** - * Handles the status output from GPG for the sign operation - * - * This method is responsible for sending the passphrase commands when - * required by the {@link Crypt_GPG::sign()} method. See doc/DETAILS - * in the {@link http://www.gnupg.org/download/ GPG distribution} for - * detailed information on GPG's status output. - * - * @param string $line the status line to handle. - * - * @return void - * - * @see Crypt_GPG::sign() - */ - public function handleSignStatus($line) - { - $tokens = explode(' ', $line); - switch ($tokens[0]) { - case 'NEED_PASSPHRASE': - $subKeyId = $tokens[1]; - if (array_key_exists($subKeyId, $this->signKeys)) { - $passphrase = $this->signKeys[$subKeyId]['passphrase']; - $this->engine->sendCommand($passphrase); - } else { - $this->engine->sendCommand(''); - } - break; - } - } - - // }}} - // {{{ handleImportKeyStatus() - - /** - * Handles the status output from GPG for the import operation - * - * This method is responsible for building the result array that is - * returned from the {@link Crypt_GPG::importKey()} method. See - * doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG distribution} for detailed - * information on GPG's status output. - * - * @param string $line the status line to handle. - * @param array &$result the current result array being processed. - * - * @return void - * - * @see Crypt_GPG::importKey() - * @see Crypt_GPG::importKeyFile() - * @see Crypt_GPG_Engine::addStatusHandler() - */ - public function handleImportKeyStatus($line, array &$result) - { - $tokens = explode(' ', $line); - switch ($tokens[0]) { - case 'IMPORT_OK': - $result['fingerprint'] = $tokens[2]; - break; - - case 'IMPORT_RES': - $result['public_imported'] = intval($tokens[3]); - $result['public_unchanged'] = intval($tokens[5]); - $result['private_imported'] = intval($tokens[11]); - $result['private_unchanged'] = intval($tokens[12]); - break; - } - } - - // }}} - // {{{ _addKey() - - /** - * Adds a key to one of the internal key arrays - * - * This handles resolving full key objects from the provided - * $key value. - * - * @param array &$array the array to which the key should be added. - * @param boolean $encrypt whether or not the key must be able to - * encrypt. - * @param boolean $sign whether or not the key must be able to sign. - * @param mixed $key the key to add. This may be a key identifier, - * user id, fingerprint, {@link Crypt_GPG_Key} or - * {@link Crypt_GPG_SubKey}. - * @param string $passphrase optional. The passphrase associated with the - * key. - * - * @return void - * - * @sensitive $passphrase - */ - protected function _addKey(array &$array, $encrypt, $sign, $key, - $passphrase = null - ) { - $subKeys = array(); - - if (is_scalar($key)) { - $keys = $this->getKeys($key); - if (count($keys) == 0) { - throw new Crypt_GPG_KeyNotFoundException( - 'Key "' . $key . '" not found.', - 0, - $key - ); - } - $key = $keys[0]; - } - - if ($key instanceof Crypt_GPG_Key) { - if ($encrypt && !$key->canEncrypt()) { - throw new InvalidArgumentException( - 'Key "' . $key . '" cannot encrypt.' - ); - } - - if ($sign && !$key->canSign()) { - throw new InvalidArgumentException( - 'Key "' . $key . '" cannot sign.' - ); - } - - foreach ($key->getSubKeys() as $subKey) { - $canEncrypt = $subKey->canEncrypt(); - $canSign = $subKey->canSign(); - if ( ($encrypt && $sign && $canEncrypt && $canSign) - || ($encrypt && !$sign && $canEncrypt) - || (!$encrypt && $sign && $canSign) - ) { - // We add all subkeys that meet the requirements because we - // were not told which subkey is required. - $subKeys[] = $subKey; - } - } - } elseif ($key instanceof Crypt_GPG_SubKey) { - $subKeys[] = $key; - } - - if (count($subKeys) === 0) { - throw new InvalidArgumentException( - 'Key "' . $key . '" is not in a recognized format.' - ); - } - - foreach ($subKeys as $subKey) { - if ($encrypt && !$subKey->canEncrypt()) { - throw new InvalidArgumentException( - 'Key "' . $key . '" cannot encrypt.' - ); - } - - if ($sign && !$subKey->canSign()) { - throw new InvalidArgumentException( - 'Key "' . $key . '" cannot sign.' - ); - } - - $array[$subKey->getId()] = array( - 'fingerprint' => $subKey->getFingerprint(), - 'passphrase' => $passphrase - ); - } - } - - // }}} - // {{{ _setPinEntryEnv() - - /** - * Sets the PINENTRY_USER_DATA environment variable with the currently - * added keys and passphrases - * - * Keys and pasphrases are stored as an indexed array of associative - * arrays that is JSON encoded to a flat string. - * - * For GnuPG 2.x this is how passphrases are passed. For GnuPG 1.x the - * environment variable is set but not used. - * - * @param array $keys the internal key array to use. - * - * @return void - */ - protected function _setPinEntryEnv(array $keys) - { - $envKeys = array(); - foreach ($keys as $id => $key) { - $envKeys[] = array( - 'keyId' => $id, - 'fingerprint' => $key['fingerprint'], - 'passphrase' => $key['passphrase'] - ); - } - $envKeys = json_encode($envKeys); - $_ENV['PINENTRY_USER_DATA'] = $envKeys; - } - - // }}} - // {{{ _importKey() - - /** - * Imports a public or private key into the keyring - * - * @param string $key the key to be imported. - * @param boolean $isFile whether or not the input is a filename. - * - * @return array an associative array containing the following elements: - * - fingerprint - the fingerprint of the - * imported key, - * - public_imported - the number of public - * keys imported, - * - public_unchanged - the number of unchanged - * public keys, - * - private_imported - the number of private - * keys imported, - * - private_unchanged - the number of unchanged - * private keys. - * - * @throws Crypt_GPG_NoDataException if the key data is missing or if the - * data is is not valid key data. - * - * @throws Crypt_GPG_FileException if the key file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - protected function _importKey($key, $isFile) - { - $result = array(); - - if ($isFile) { - $input = @fopen($key, 'rb'); - if ($input === false) { - throw new Crypt_GPG_FileException( - 'Could not open key file "' . $key . '" for importing.', - 0, - $key - ); - } - } else { - $input = strval($key); - if ($input == '') { - throw new Crypt_GPG_NoDataException( - 'No valid GPG key data found.', - self::ERROR_NO_DATA - ); - } - } - - $arguments = array(); - $version = $this->engine->getVersion(); - - if ( version_compare($version, '1.0.5', 'ge') - && version_compare($version, '1.0.7', 'lt') - ) { - $arguments[] = '--allow-secret-key-import'; - } - - $this->engine->reset(); - $this->engine->addStatusHandler( - array($this, 'handleImportKeyStatus'), - array(&$result) - ); - - $this->engine->setOperation('--import', $arguments); - $this->engine->setInput($input); - $this->engine->run(); - - if ($isFile) { - fclose($input); - } - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_DUPLICATE_KEY: - case self::ERROR_NONE: - // ignore duplicate key import errors - break; - case self::ERROR_NO_DATA: - throw new Crypt_GPG_NoDataException( - 'No valid GPG key data found.', - $code - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error importing GPG key. Please use the \'debug\' ' . - 'option when creating the Crypt_GPG object, and file a bug ' . - 'report at ' . self::BUG_URI, - $code - ); - } - - return $result; - } - - // }}} - // {{{ _encrypt() - - /** - * Encrypts data - * - * @param string $data the data to encrypt. - * @param boolean $isFile whether or not the data is a filename. - * @param string $outputFile the filename of the file in which to store - * the encrypted data. If null, the encrypted - * data is returned as a string. - * @param boolean $armor if true, ASCII armored data is returned; - * otherwise, binary data is returned. - * - * @return void|string if the $outputFile parameter is null, a - * string containing the encrypted data is returned. - * - * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified. - * See {@link Crypt_GPG::addEncryptKey()}. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - protected function _encrypt($data, $isFile, $outputFile, $armor) - { - if (count($this->encryptKeys) === 0) { - throw new Crypt_GPG_KeyNotFoundException( - 'No encryption keys specified.' - ); - } - - if ($isFile) { - $input = @fopen($data, 'rb'); - if ($input === false) { - throw new Crypt_GPG_FileException( - 'Could not open input file "' . $data . - '" for encryption.', - 0, - $data - ); - } - } else { - $input = strval($data); - } - - if ($outputFile === null) { - $output = ''; - } else { - $output = @fopen($outputFile, 'wb'); - if ($output === false) { - if ($isFile) { - fclose($input); - } - throw new Crypt_GPG_FileException( - 'Could not open output file "' . $outputFile . - '" for storing encrypted data.', - 0, - $outputFile - ); - } - } - - $arguments = ($armor) ? array('--armor') : array(); - foreach ($this->encryptKeys as $key) { - $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']); - } - - $this->engine->reset(); - $this->engine->setInput($input); - $this->engine->setOutput($output); - $this->engine->setOperation('--encrypt', $arguments); - $this->engine->run(); - - if ($isFile) { - fclose($input); - } - - if ($outputFile !== null) { - fclose($output); - } - - $code = $this->engine->getErrorCode(); - - if ($code !== self::ERROR_NONE) { - throw new Crypt_GPG_Exception( - 'Unknown error encrypting data. Please use the \'debug\' ' . - 'option when creating the Crypt_GPG object, and file a bug ' . - 'report at ' . self::BUG_URI, - $code - ); - } - - if ($outputFile === null) { - return $output; - } - } - - // }}} - // {{{ _decrypt() - - /** - * Decrypts data - * - * @param string $data the data to be decrypted. - * @param boolean $isFile whether or not the data is a filename. - * @param string $outputFile the name of the file to which the decrypted - * data should be written. If null, the decrypted - * data is returned as a string. - * - * @return void|string if the $outputFile parameter is null, a - * string containing the decrypted data is returned. - * - * @throws Crypt_GPG_KeyNotFoundException if the private key needed to - * decrypt the data is not in the user's keyring. - * - * @throws Crypt_GPG_NoDataException if specified data does not contain - * GPG encrypted data. - * - * @throws Crypt_GPG_BadPassphraseException if a required passphrase is - * incorrect or if a required passphrase is not specified. See - * {@link Crypt_GPG::addDecryptKey()}. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - protected function _decrypt($data, $isFile, $outputFile) - { - if ($isFile) { - $input = @fopen($data, 'rb'); - if ($input === false) { - throw new Crypt_GPG_FileException( - 'Could not open input file "' . $data . - '" for decryption.', - 0, - $data - ); - } - } else { - $input = strval($data); - if ($input == '') { - throw new Crypt_GPG_NoDataException( - 'Cannot decrypt data. No PGP encrypted data was found in '. - 'the provided data.', - self::ERROR_NO_DATA - ); - } - } - - if ($outputFile === null) { - $output = ''; - } else { - $output = @fopen($outputFile, 'wb'); - if ($output === false) { - if ($isFile) { - fclose($input); - } - throw new Crypt_GPG_FileException( - 'Could not open output file "' . $outputFile . - '" for storing decrypted data.', - 0, - $outputFile - ); - } - } - - $handler = new Crypt_GPG_DecryptStatusHandler( - $this->engine, - $this->decryptKeys - ); - - // If using gpg-agent, set the decrypt pins used by the pinentry - $this->_setPinEntryEnv($this->decryptKeys); - - $this->engine->reset(); - $this->engine->addStatusHandler(array($handler, 'handle')); - $this->engine->setOperation('--decrypt'); - $this->engine->setInput($input); - $this->engine->setOutput($output); - $this->engine->run(); - - if ($isFile) { - fclose($input); - } - - if ($outputFile !== null) { - fclose($output); - } - - // if there was any problem decrypting the data, the handler will - // deal with it here. - $handler->throwException(); - - if ($outputFile === null) { - return $output; - } - } - - // }}} - // {{{ _sign() - - /** - * Signs data - * - * @param string $data the data to be signed. - * @param boolean $isFile whether or not the data is a filename. - * @param string $outputFile the name of the file in which the signed data - * should be stored. If null, the signed data is - * returned as a string. - * @param boolean $mode the data signing mode to use. Should be one of - * {@link Crypt_GPG::SIGN_MODE_NORMAL}, - * {@link Crypt_GPG::SIGN_MODE_CLEAR} or - * {@link Crypt_GPG::SIGN_MODE_DETACHED}. - * @param boolean $armor if true, ASCII armored data is returned; - * otherwise, binary data is returned. This has - * no effect if the mode - * Crypt_GPG::SIGN_MODE_CLEAR is - * used. - * @param boolean $textmode if true, line-breaks in signed data be - * normalized. Use this option when signing - * e-mail, or for greater compatibility between - * systems with different line-break formats. - * Defaults to false. This has no effect if the - * mode Crypt_GPG::SIGN_MODE_CLEAR is - * used as clear-signing always uses textmode. - * - * @return void|string if the $outputFile parameter is null, a - * string containing the signed data (or the signature - * data if a detached signature is requested) is - * returned. - * - * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified. - * See {@link Crypt_GPG::addSignKey()}. - * - * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is - * incorrect or if a required passphrase is not specified. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - protected function _sign($data, $isFile, $outputFile, $mode, $armor, - $textmode - ) { - if (count($this->signKeys) === 0) { - throw new Crypt_GPG_KeyNotFoundException( - 'No signing keys specified.' - ); - } - - if ($isFile) { - $input = @fopen($data, 'rb'); - if ($input === false) { - throw new Crypt_GPG_FileException( - 'Could not open input file "' . $data . '" for signing.', - 0, - $data - ); - } - } else { - $input = strval($data); - } - - if ($outputFile === null) { - $output = ''; - } else { - $output = @fopen($outputFile, 'wb'); - if ($output === false) { - if ($isFile) { - fclose($input); - } - throw new Crypt_GPG_FileException( - 'Could not open output file "' . $outputFile . - '" for storing signed data.', - 0, - $outputFile - ); - } - } - - switch ($mode) { - case self::SIGN_MODE_DETACHED: - $operation = '--detach-sign'; - break; - case self::SIGN_MODE_CLEAR: - $operation = '--clearsign'; - break; - case self::SIGN_MODE_NORMAL: - default: - $operation = '--sign'; - break; - } - - $arguments = array(); - - if ($armor) { - $arguments[] = '--armor'; - } - if ($textmode) { - $arguments[] = '--textmode'; - } - - foreach ($this->signKeys as $key) { - $arguments[] = '--local-user ' . - escapeshellarg($key['fingerprint']); - } - - // If using gpg-agent, set the sign pins used by the pinentry - $this->_setPinEntryEnv($this->signKeys); - - $this->engine->reset(); - $this->engine->addStatusHandler(array($this, 'handleSignStatus')); - $this->engine->setInput($input); - $this->engine->setOutput($output); - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - if ($isFile) { - fclose($input); - } - - if ($outputFile !== null) { - fclose($output); - } - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - break; - case self::ERROR_KEY_NOT_FOUND: - throw new Crypt_GPG_KeyNotFoundException( - 'Cannot sign data. Private key not found. Import the '. - 'private key before trying to sign data.', - $code, - $this->engine->getErrorKeyId() - ); - case self::ERROR_BAD_PASSPHRASE: - throw new Crypt_GPG_BadPassphraseException( - 'Cannot sign data. Incorrect passphrase provided.', - $code - ); - case self::ERROR_MISSING_PASSPHRASE: - throw new Crypt_GPG_BadPassphraseException( - 'Cannot sign data. No passphrase provided.', - $code - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error signing data. Please use the \'debug\' option ' . - 'when creating the Crypt_GPG object, and file a bug report ' . - 'at ' . self::BUG_URI, - $code - ); - } - - if ($outputFile === null) { - return $output; - } - } - - // }}} - // {{{ _encryptAndSign() - - /** - * Encrypts and signs data - * - * @param string $data the data to be encrypted and signed. - * @param boolean $isFile whether or not the data is a filename. - * @param string $outputFile the name of the file in which the encrypted, - * signed data should be stored. If null, the - * encrypted, signed data is returned as a - * string. - * @param boolean $armor if true, ASCII armored data is returned; - * otherwise, binary data is returned. - * - * @return void|string if the $outputFile parameter is null, a - * string containing the encrypted, signed data is - * returned. - * - * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified - * or if no signing key is specified. See - * {@link Crypt_GPG::addEncryptKey()} and - * {@link Crypt_GPG::addSignKey()}. - * - * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is - * incorrect or if a required passphrase is not specified. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - protected function _encryptAndSign($data, $isFile, $outputFile, $armor) - { - if (count($this->signKeys) === 0) { - throw new Crypt_GPG_KeyNotFoundException( - 'No signing keys specified.' - ); - } - - if (count($this->encryptKeys) === 0) { - throw new Crypt_GPG_KeyNotFoundException( - 'No encryption keys specified.' - ); - } - - - if ($isFile) { - $input = @fopen($data, 'rb'); - if ($input === false) { - throw new Crypt_GPG_FileException( - 'Could not open input file "' . $data . - '" for encrypting and signing.', - 0, - $data - ); - } - } else { - $input = strval($data); - } - - if ($outputFile === null) { - $output = ''; - } else { - $output = @fopen($outputFile, 'wb'); - if ($output === false) { - if ($isFile) { - fclose($input); - } - throw new Crypt_GPG_FileException( - 'Could not open output file "' . $outputFile . - '" for storing encrypted, signed data.', - 0, - $outputFile - ); - } - } - - $arguments = ($armor) ? array('--armor') : array(); - - foreach ($this->signKeys as $key) { - $arguments[] = '--local-user ' . - escapeshellarg($key['fingerprint']); - } - - // If using gpg-agent, set the sign pins used by the pinentry - $this->_setPinEntryEnv($this->signKeys); - - foreach ($this->encryptKeys as $key) { - $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']); - } - - $this->engine->reset(); - $this->engine->addStatusHandler(array($this, 'handleSignStatus')); - $this->engine->setInput($input); - $this->engine->setOutput($output); - $this->engine->setOperation('--encrypt --sign', $arguments); - $this->engine->run(); - - if ($isFile) { - fclose($input); - } - - if ($outputFile !== null) { - fclose($output); - } - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - break; - case self::ERROR_KEY_NOT_FOUND: - throw new Crypt_GPG_KeyNotFoundException( - 'Cannot sign encrypted data. Private key not found. Import '. - 'the private key before trying to sign the encrypted data.', - $code, - $this->engine->getErrorKeyId() - ); - case self::ERROR_BAD_PASSPHRASE: - throw new Crypt_GPG_BadPassphraseException( - 'Cannot sign encrypted data. Incorrect passphrase provided.', - $code - ); - case self::ERROR_MISSING_PASSPHRASE: - throw new Crypt_GPG_BadPassphraseException( - 'Cannot sign encrypted data. No passphrase provided.', - $code - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error encrypting and signing data. Please use the ' . - '\'debug\' option when creating the Crypt_GPG object, and ' . - 'file a bug report at ' . self::BUG_URI, - $code - ); - } - - if ($outputFile === null) { - return $output; - } - } - - // }}} - // {{{ _verify() - - /** - * Verifies data - * - * @param string $data the signed data to be verified. - * @param boolean $isFile whether or not the data is a filename. - * @param string $signature if verifying a file signed using a detached - * signature, this must be the detached signature - * data. Otherwise, specify ''. - * - * @return array an array of {@link Crypt_GPG_Signature} objects for the - * signed data. - * - * @throws Crypt_GPG_NoDataException if the provided data is not signed - * data. - * - * @throws Crypt_GPG_FileException if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG_Signature - */ - protected function _verify($data, $isFile, $signature) - { - if ($signature == '') { - $operation = '--verify'; - $arguments = array(); - } else { - // Signed data goes in FD_MESSAGE, detached signature data goes in - // FD_INPUT. - $operation = '--verify - "-&' . Crypt_GPG_Engine::FD_MESSAGE. '"'; - $arguments = array('--enable-special-filenames'); - } - - $handler = new Crypt_GPG_VerifyStatusHandler(); - - if ($isFile) { - $input = @fopen($data, 'rb'); - if ($input === false) { - throw new Crypt_GPG_FileException( - 'Could not open input file "' . $data . '" for verifying.', - 0, - $data - ); - } - } else { - $input = strval($data); - if ($input == '') { - throw new Crypt_GPG_NoDataException( - 'No valid signature data found.', - self::ERROR_NO_DATA - ); - } - } - - $this->engine->reset(); - $this->engine->addStatusHandler(array($handler, 'handle')); - - if ($signature == '') { - // signed or clearsigned data - $this->engine->setInput($input); - } else { - // detached signature - $this->engine->setInput($signature); - $this->engine->setMessage($input); - } - - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - if ($isFile) { - fclose($input); - } - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - case self::ERROR_BAD_SIGNATURE: - break; - case self::ERROR_NO_DATA: - throw new Crypt_GPG_NoDataException( - 'No valid signature data found.', - $code - ); - case self::ERROR_KEY_NOT_FOUND: - throw new Crypt_GPG_KeyNotFoundException( - 'Public key required for data verification not in keyring.', - $code, - $this->engine->getErrorKeyId() - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error validating signature details. Please use the ' . - '\'debug\' option when creating the Crypt_GPG object, and ' . - 'file a bug report at ' . self::BUG_URI, - $code - ); - } - - return $handler->getSignatures(); - } - - // }}} - // {{{ _decryptAndVerify() - - /** - * Decrypts and verifies encrypted, signed data - * - * @param string $data the encrypted signed data to be decrypted and - * verified. - * @param boolean $isFile whether or not the data is a filename. - * @param string $outputFile the name of the file to which the decrypted - * data should be written. If null, the decrypted - * data is returned in the results array. - * - * @return array two element array. The array has an element 'data' - * containing the decrypted data and an element - * 'signatures' containing an array of - * {@link Crypt_GPG_Signature} objects for the signed data. - * If the decrypted data is written to a file, the 'data' - * element is null. - * - * @throws Crypt_GPG_KeyNotFoundException if the private key needed to - * decrypt the data is not in the user's keyring or it the public - * key needed for verification is not in the user's keyring. - * - * @throws Crypt_GPG_NoDataException if specified data does not contain - * GPG signed, encrypted data. - * - * @throws Crypt_GPG_BadPassphraseException if a required passphrase is - * incorrect or if a required passphrase is not specified. See - * {@link Crypt_GPG::addDecryptKey()}. - * - * @throws Crypt_GPG_FileException if the output file is not writeable or - * if the input file is not readable. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG_Signature - */ - protected function _decryptAndVerify($data, $isFile, $outputFile) - { - if ($isFile) { - $input = @fopen($data, 'rb'); - if ($input === false) { - throw new Crypt_GPG_FileException( - 'Could not open input file "' . $data . - '" for decrypting and verifying.', - 0, - $data - ); - } - } else { - $input = strval($data); - if ($input == '') { - throw new Crypt_GPG_NoDataException( - 'No valid encrypted signed data found.', - self::ERROR_NO_DATA - ); - } - } - - if ($outputFile === null) { - $output = ''; - } else { - $output = @fopen($outputFile, 'wb'); - if ($output === false) { - if ($isFile) { - fclose($input); - } - throw new Crypt_GPG_FileException( - 'Could not open output file "' . $outputFile . - '" for storing decrypted data.', - 0, - $outputFile - ); - } - } - - $verifyHandler = new Crypt_GPG_VerifyStatusHandler(); - - $decryptHandler = new Crypt_GPG_DecryptStatusHandler( - $this->engine, - $this->decryptKeys - ); - - // If using gpg-agent, set the decrypt pins used by the pinentry - $this->_setPinEntryEnv($this->decryptKeys); - - $this->engine->reset(); - $this->engine->addStatusHandler(array($verifyHandler, 'handle')); - $this->engine->addStatusHandler(array($decryptHandler, 'handle')); - $this->engine->setInput($input); - $this->engine->setOutput($output); - $this->engine->setOperation('--decrypt'); - $this->engine->run(); - - if ($isFile) { - fclose($input); - } - - if ($outputFile !== null) { - fclose($output); - } - - $return = array( - 'data' => null, - 'signatures' => $verifyHandler->getSignatures() - ); - - // if there was any problem decrypting the data, the handler will - // deal with it here. - try { - $decryptHandler->throwException(); - } catch (Exception $e) { - if ($e instanceof Crypt_GPG_KeyNotFoundException) { - throw new Crypt_GPG_KeyNotFoundException( - 'Public key required for data verification not in ', - 'the keyring. Either no suitable private decryption key ' . - 'is in the keyring or the public key required for data ' . - 'verification is not in the keyring. Import a suitable ' . - 'key before trying to decrypt and verify this data.', - self::ERROR_KEY_NOT_FOUND, - $this->engine->getErrorKeyId() - ); - } - - if ($e instanceof Crypt_GPG_NoDataException) { - throw new Crypt_GPG_NoDataException( - 'Cannot decrypt and verify data. No PGP encrypted data ' . - 'was found in the provided data.', - self::ERROR_NO_DATA - ); - } - - throw $e; - } - - if ($outputFile === null) { - $return['data'] = $output; - } - - return $return; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/ByteUtils.php b/program/lib/Crypt/GPG/ByteUtils.php deleted file mode 100644 index 342905471..000000000 --- a/program/lib/Crypt/GPG/ByteUtils.php +++ /dev/null @@ -1,105 +0,0 @@ - - * @copyright 2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -// {{{ class Crypt_GPG_ByteUtils - -/** - * A class for performing byte-wise string operations - * - * GPG I/O streams are managed using bytes rather than characters. This class - * requires the mbstring extension to be available. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://php.net/mbstring - */ -class Crypt_GPG_ByteUtils -{ - // {{{ strlen() - - /** - * Gets the length of a string in bytes - * - * This is used for stream-based communication with the GPG subprocess. - * - * @param string $string the string for which to get the length. - * - * @return integer the length of the string in bytes. - */ - public static function strlen($string) - { - return mb_strlen($string, '8bit'); - } - - // }}} - // {{{ substr() - - /** - * Gets the substring of a string in bytes - * - * This is used for stream-based communication with the GPG subprocess. - * - * @param string $string the input string. - * @param integer $start the starting point at which to get the substring. - * @param integer $length optional. The length of the substring. - * - * @return string the extracted part of the string. Unlike the default PHP - * substr() function, the returned value is - * always a string and never false. - */ - public static function substr($string, $start, $length = null) - { - if ($length === null) { - return mb_substr( - $string, - $start, - self::strlen($string) - $start, '8bit' - ); - } - - return mb_substr($string, $start, $length, '8bit'); - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/DecryptStatusHandler.php b/program/lib/Crypt/GPG/DecryptStatusHandler.php deleted file mode 100644 index 67c0dd74b..000000000 --- a/program/lib/Crypt/GPG/DecryptStatusHandler.php +++ /dev/null @@ -1,344 +0,0 @@ - - * @copyright 2008-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ - -/** - * Crypt_GPG base class - */ -require_once 'Crypt/GPG.php'; - -/** - * Crypt_GPG exception classes - */ -require_once 'Crypt/GPG/Exceptions.php'; - - -/** - * Status line handler for the decrypt operation - * - * This class is used internally by Crypt_GPG and does not need be used - * directly. See the {@link Crypt_GPG} class for end-user API. - * - * This class is responsible for sending the passphrase commands when required - * by the {@link Crypt_GPG::decrypt()} method. See doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GnuPG distribution} for detailed - * information on GnuPG's status output for the decrypt operation. - * - * This class is also responsible for parsing error status and throwing a - * meaningful exception in the event that decryption fails. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2008-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -class Crypt_GPG_DecryptStatusHandler -{ - // {{{ protected properties - - /** - * Keys used to decrypt - * - * The array is of the form: - * - * array( - * $key_id => array( - * 'fingerprint' => $fingerprint, - * 'passphrase' => $passphrase - * ) - * ); - * - * - * @var array - */ - protected $keys = array(); - - /** - * Engine used to which passphrases are passed - * - * @var Crypt_GPG_Engine - */ - protected $engine = null; - - /** - * The id of the current sub-key used for decryption - * - * @var string - */ - protected $currentSubKey = ''; - - /** - * Whether or not decryption succeeded - * - * If the message is only signed (compressed) and not encrypted, this is - * always true. If the message is encrypted, this flag is set to false - * until we know the decryption succeeded. - * - * @var boolean - */ - protected $decryptionOkay = true; - - /** - * Whether or not there was no data for decryption - * - * @var boolean - */ - protected $noData = false; - - /** - * Keys for which the passhprase is missing - * - * This contains primary user ids indexed by sub-key id and is used to - * create helpful exception messages. - * - * @var array - */ - protected $missingPassphrases = array(); - - /** - * Keys for which the passhprase is incorrect - * - * This contains primary user ids indexed by sub-key id and is used to - * create helpful exception messages. - * - * @var array - */ - protected $badPassphrases = array(); - - /** - * Keys that can be used to decrypt the data but are missing from the - * keychain - * - * This is an array with both the key and value being the sub-key id of - * the missing keys. - * - * @var array - */ - protected $missingKeys = array(); - - // }}} - // {{{ __construct() - - /** - * Creates a new decryption status handler - * - * @param Crypt_GPG_Engine $engine the GPG engine to which passphrases are - * passed. - * @param array $keys the decryption keys to use. - */ - public function __construct(Crypt_GPG_Engine $engine, array $keys) - { - $this->engine = $engine; - $this->keys = $keys; - } - - // }}} - // {{{ handle() - - /** - * Handles a status line - * - * @param string $line the status line to handle. - * - * @return void - */ - public function handle($line) - { - $tokens = explode(' ', $line); - switch ($tokens[0]) { - case 'ENC_TO': - // Now we know the message is encrypted. Set flag to check if - // decryption succeeded. - $this->decryptionOkay = false; - - // this is the new key message - $this->currentSubKeyId = $tokens[1]; - break; - - case 'NEED_PASSPHRASE': - // send passphrase to the GPG engine - $subKeyId = $tokens[1]; - if (array_key_exists($subKeyId, $this->keys)) { - $passphrase = $this->keys[$subKeyId]['passphrase']; - $this->engine->sendCommand($passphrase); - } else { - $this->engine->sendCommand(''); - } - break; - - case 'USERID_HINT': - // remember the user id for pretty exception messages - $this->badPassphrases[$tokens[1]] - = implode(' ', array_splice($tokens, 2)); - - break; - - case 'GOOD_PASSPHRASE': - // if we got a good passphrase, remove the key from the list of - // bad passphrases. - unset($this->badPassphrases[$this->currentSubKeyId]); - break; - - case 'MISSING_PASSPHRASE': - $this->missingPassphrases[$this->currentSubKeyId] - = $this->currentSubKeyId; - - break; - - case 'NO_SECKEY': - // note: this message is also received if there are multiple - // recipients and a previous key had a correct passphrase. - $this->missingKeys[$tokens[1]] = $tokens[1]; - break; - - case 'NODATA': - $this->noData = true; - break; - - case 'DECRYPTION_OKAY': - // If the message is encrypted, this is the all-clear signal. - $this->decryptionOkay = true; - break; - } - } - - // }}} - // {{{ throwException() - - /** - * Takes the final status of the decrypt operation and throws an - * appropriate exception - * - * If decryption was successful, no exception is thrown. - * - * @return void - * - * @throws Crypt_GPG_KeyNotFoundException if the private key needed to - * decrypt the data is not in the user's keyring. - * - * @throws Crypt_GPG_NoDataException if specified data does not contain - * GPG encrypted data. - * - * @throws Crypt_GPG_BadPassphraseException if a required passphrase is - * incorrect or if a required passphrase is not specified. See - * {@link Crypt_GPG::addDecryptKey()}. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function throwException() - { - $code = Crypt_GPG::ERROR_NONE; - - if (!$this->decryptionOkay) { - if (count($this->badPassphrases) > 0) { - $code = Crypt_GPG::ERROR_BAD_PASSPHRASE; - } elseif (count($this->missingKeys) > 0) { - $code = Crypt_GPG::ERROR_KEY_NOT_FOUND; - } else { - $code = Crypt_GPG::ERROR_UNKNOWN; - } - } elseif ($this->noData) { - $code = Crypt_GPG::ERROR_NO_DATA; - } - - switch ($code) { - case Crypt_GPG::ERROR_NONE: - break; - - case Crypt_GPG::ERROR_KEY_NOT_FOUND: - if (count($this->missingKeys) > 0) { - $keyId = reset($this->missingKeys); - } else { - $keyId = ''; - } - throw new Crypt_GPG_KeyNotFoundException( - 'Cannot decrypt data. No suitable private key is in the ' . - 'keyring. Import a suitable private key before trying to ' . - 'decrypt this data.', - $code, - $keyId - ); - case Crypt_GPG::ERROR_BAD_PASSPHRASE: - $badPassphrases = array_diff_key( - $this->badPassphrases, - $this->missingPassphrases - ); - - $missingPassphrases = array_intersect_key( - $this->badPassphrases, - $this->missingPassphrases - ); - - $message = 'Cannot decrypt data.'; - if (count($badPassphrases) > 0) { - $message = ' Incorrect passphrase provided for keys: "' . - implode('", "', $badPassphrases) . '".'; - } - if (count($missingPassphrases) > 0) { - $message = ' No passphrase provided for keys: "' . - implode('", "', $badPassphrases) . '".'; - } - - throw new Crypt_GPG_BadPassphraseException( - $message, - $code, - $badPassphrases, - $missingPassphrases - ); - case Crypt_GPG::ERROR_NO_DATA: - throw new Crypt_GPG_NoDataException( - 'Cannot decrypt data. No PGP encrypted data was found in '. - 'the provided data.', - $code - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error decrypting data.', - $code - ); - } - } - - // }}} -} - -?> diff --git a/program/lib/Crypt/GPG/Engine.php b/program/lib/Crypt/GPG/Engine.php deleted file mode 100644 index 601541443..000000000 --- a/program/lib/Crypt/GPG/Engine.php +++ /dev/null @@ -1,2006 +0,0 @@ - - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ - -/** - * Crypt_GPG base class. - */ -require_once 'Crypt/GPG.php'; - -/** - * GPG exception classes. - */ -require_once 'Crypt/GPG/Exceptions.php'; - -/** - * Byte string operations. - */ -require_once 'Crypt/GPG/ByteUtils.php'; - -/** - * Process control methods. - */ -require_once 'Crypt/GPG/ProcessControl.php'; - -/** - * Standard PEAR exception is used if GPG binary is not found. - */ -require_once 'PEAR/Exception.php'; - -// {{{ class Crypt_GPG_Engine - -/** - * Native PHP Crypt_GPG I/O engine - * - * This class is used internally by Crypt_GPG and does not need be used - * directly. See the {@link Crypt_GPG} class for end-user API. - * - * This engine uses PHP's native process control functions to directly control - * the GPG process. The GPG executable is required to be on the system. - * - * All data is passed to the GPG subprocess using file descriptors. This is the - * most secure method of passing data to the GPG subprocess. - * - * @category Encryption - * @package Crypt_GPG - * @author Nathan Fredrickson - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -class Crypt_GPG_Engine -{ - // {{{ constants - - /** - * Size of data chunks that are sent to and retrieved from the IPC pipes. - * - * PHP reads 8192 bytes. If this is set to less than 8192, PHP reads 8192 - * and buffers the rest so we might as well just read 8192. - * - * Using values other than 8192 also triggers PHP bugs. - * - * @see http://bugs.php.net/bug.php?id=35224 - */ - const CHUNK_SIZE = 8192; - - /** - * Standard input file descriptor. This is used to pass data to the GPG - * process. - */ - const FD_INPUT = 0; - - /** - * Standard output file descriptor. This is used to receive normal output - * from the GPG process. - */ - const FD_OUTPUT = 1; - - /** - * Standard output file descriptor. This is used to receive error output - * from the GPG process. - */ - const FD_ERROR = 2; - - /** - * GPG status output file descriptor. The status file descriptor outputs - * detailed information for many GPG commands. See the second section of - * the file doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG package} for a detailed - * description of GPG's status output. - */ - const FD_STATUS = 3; - - /** - * Command input file descriptor. This is used for methods requiring - * passphrases. - */ - const FD_COMMAND = 4; - - /** - * Extra message input file descriptor. This is used for passing signed - * data when verifying a detached signature. - */ - const FD_MESSAGE = 5; - - /** - * Minimum version of GnuPG that is supported. - */ - const MIN_VERSION = '1.0.2'; - - // }}} - // {{{ private class properties - - /** - * Whether or not to use debugging mode - * - * When set to true, every GPG command is echoed before it is run. Sensitive - * data is always handled using pipes and is not specified as part of the - * command. As a result, sensitive data is never displayed when debug is - * enabled. Sensitive data includes private key data and passphrases. - * - * Debugging is off by default. - * - * @var boolean - * @see Crypt_GPG_Engine::__construct() - */ - private $_debug = false; - - /** - * Location of GPG binary - * - * @var string - * @see Crypt_GPG_Engine::__construct() - * @see Crypt_GPG_Engine::_getBinary() - */ - private $_binary = ''; - - /** - * Location of GnuPG agent binary - * - * Only used for GnuPG 2.x - * - * @var string - * @see Crypt_GPG_Engine::__construct() - * @see Crypt_GPG_Engine::_getAgent() - */ - private $_agent = ''; - - /** - * Directory containing the GPG key files - * - * This property only contains the path when the homedir option - * is specified in the constructor. - * - * @var string - * @see Crypt_GPG_Engine::__construct() - */ - private $_homedir = ''; - - /** - * File path of the public keyring - * - * This property only contains the file path when the public_keyring - * option is specified in the constructor. - * - * If the specified file path starts with ~/, the path is - * relative to the homedir if specified, otherwise to - * ~/.gnupg. - * - * @var string - * @see Crypt_GPG_Engine::__construct() - */ - private $_publicKeyring = ''; - - /** - * File path of the private (secret) keyring - * - * This property only contains the file path when the private_keyring - * option is specified in the constructor. - * - * If the specified file path starts with ~/, the path is - * relative to the homedir if specified, otherwise to - * ~/.gnupg. - * - * @var string - * @see Crypt_GPG_Engine::__construct() - */ - private $_privateKeyring = ''; - - /** - * File path of the trust database - * - * This property only contains the file path when the trust_db - * option is specified in the constructor. - * - * If the specified file path starts with ~/, the path is - * relative to the homedir if specified, otherwise to - * ~/.gnupg. - * - * @var string - * @see Crypt_GPG_Engine::__construct() - */ - private $_trustDb = ''; - - /** - * Array of pipes used for communication with the GPG binary - * - * This is an array of file descriptor resources. - * - * @var array - */ - private $_pipes = array(); - - /** - * Array of pipes used for communication with the gpg-agent binary - * - * This is an array of file descriptor resources. - * - * @var array - */ - private $_agentPipes = array(); - - /** - * Array of currently opened pipes - * - * This array is used to keep track of remaining opened pipes so they can - * be closed when the GPG subprocess is finished. This array is a subset of - * the {@link Crypt_GPG_Engine::$_pipes} array and contains opened file - * descriptor resources. - * - * @var array - * @see Crypt_GPG_Engine::_closePipe() - */ - private $_openPipes = array(); - - /** - * A handle for the GPG process - * - * @var resource - */ - private $_process = null; - - /** - * A handle for the gpg-agent process - * - * @var resource - */ - private $_agentProcess = null; - - /** - * GPG agent daemon socket and PID for running gpg-agent - * - * @var string - */ - private $_agentInfo = null; - - /** - * Whether or not the operating system is Darwin (OS X) - * - * @var boolean - */ - private $_isDarwin = false; - - /** - * Commands to be sent to GPG's command input stream - * - * @var string - * @see Crypt_GPG_Engine::sendCommand() - */ - private $_commandBuffer = ''; - - /** - * Array of status line handlers - * - * @var array - * @see Crypt_GPG_Engine::addStatusHandler() - */ - private $_statusHandlers = array(); - - /** - * Array of error line handlers - * - * @var array - * @see Crypt_GPG_Engine::addErrorHandler() - */ - private $_errorHandlers = array(); - - /** - * The error code of the current operation - * - * @var integer - * @see Crypt_GPG_Engine::getErrorCode() - */ - private $_errorCode = Crypt_GPG::ERROR_NONE; - - /** - * File related to the error code of the current operation - * - * @var string - * @see Crypt_GPG_Engine::getErrorFilename() - */ - private $_errorFilename = ''; - - /** - * Key id related to the error code of the current operation - * - * @var string - * @see Crypt_GPG_Engine::getErrorKeyId() - */ - private $_errorkeyId = ''; - - /** - * The number of currently needed passphrases - * - * If this is not zero when the GPG command is completed, the error code is - * set to {@link Crypt_GPG::ERROR_MISSING_PASSPHRASE}. - * - * @var integer - */ - private $_needPassphrase = 0; - - /** - * The input source - * - * This is data to send to GPG. Either a string or a stream resource. - * - * @var string|resource - * @see Crypt_GPG_Engine::setInput() - */ - private $_input = null; - - /** - * The extra message input source - * - * Either a string or a stream resource. - * - * @var string|resource - * @see Crypt_GPG_Engine::setMessage() - */ - private $_message = null; - - /** - * The output location - * - * This is where the output from GPG is sent. Either a string or a stream - * resource. - * - * @var string|resource - * @see Crypt_GPG_Engine::setOutput() - */ - private $_output = ''; - - /** - * The GPG operation to execute - * - * @var string - * @see Crypt_GPG_Engine::setOperation() - */ - private $_operation; - - /** - * Arguments for the current operation - * - * @var array - * @see Crypt_GPG_Engine::setOperation() - */ - private $_arguments = array(); - - /** - * The version number of the GPG binary - * - * @var string - * @see Crypt_GPG_Engine::getVersion() - */ - private $_version = ''; - - // }}} - // {{{ __construct() - - /** - * Creates a new GPG engine - * - * Available options are: - * - * - string homedir - the directory where the GPG - * keyring files are stored. If not - * specified, Crypt_GPG uses the - * default of ~/.gnupg. - * - string publicKeyring - the file path of the public - * keyring. Use this if the public - * keyring is not in the homedir, or - * if the keyring is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * keyring with this option - * (/foo/bar/pubring.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string privateKeyring - the file path of the private - * keyring. Use this if the private - * keyring is not in the homedir, or - * if the keyring is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * keyring with this option - * (/foo/bar/secring.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string trustDb - the file path of the web-of-trust - * database. Use this if the trust - * database is not in the homedir, or - * if the database is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * trust database with this option - * (/foo/bar/trustdb.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string binary - the location of the GPG binary. If - * not specified, the driver attempts - * to auto-detect the GPG binary - * location using a list of known - * default locations for the current - * operating system. The option - * gpgBinary is a - * deprecated alias for this option. - * - string agent - the location of the GnuPG agent - * binary. The gpg-agent is only - * used for GnuPG 2.x. If not - * specified, the engine attempts - * to auto-detect the gpg-agent - * binary location using a list of - * know default locations for the - * current operating system. - * - boolean debug - whether or not to use debug mode. - * When debug mode is on, all - * communication to and from the GPG - * subprocess is logged. This can be - * useful to diagnose errors when - * using Crypt_GPG. - * - * @param array $options optional. An array of options used to create the - * GPG object. All options are optional and are - * represented as key-value pairs. - * - * @throws Crypt_GPG_FileException if the homedir does not exist - * and cannot be created. This can happen if homedir is - * not specified, Crypt_GPG is run as the web user, and the web - * user has no home directory. This exception is also thrown if any - * of the options publicKeyring, - * privateKeyring or trustDb options are - * specified but the files do not exist or are are not readable. - * This can happen if the user running the Crypt_GPG process (for - * example, the Apache user) does not have permission to read the - * files. - * - * @throws PEAR_Exception if the provided binary is invalid, or - * if no binary is provided and no suitable binary could - * be found. - * - * @throws PEAR_Exception if the provided agent is invalid, or - * if no agent is provided and no suitable gpg-agent - * cound be found. - */ - public function __construct(array $options = array()) - { - $this->_isDarwin = (strncmp(strtoupper(PHP_OS), 'DARWIN', 6) === 0); - - // get homedir - if (array_key_exists('homedir', $options)) { - $this->_homedir = (string)$options['homedir']; - } else { - if (extension_loaded('posix')) { - // note: this requires the package OS dep exclude 'windows' - $info = posix_getpwuid(posix_getuid()); - $this->_homedir = $info['dir'].'/.gnupg'; - } else { - if (isset($_SERVER['HOME'])) { - $this->_homedir = $_SERVER['HOME']; - } else { - $this->_homedir = getenv('HOME'); - } - } - - if ($this->_homedir === false) { - throw new Crypt_GPG_FileException( - 'Could not locate homedir. Please specify the homedir ' . - 'to use with the \'homedir\' option when instantiating ' . - 'the Crypt_GPG object.' - ); - } - } - - // attempt to create homedir if it does not exist - if (!is_dir($this->_homedir)) { - if (@mkdir($this->_homedir, 0777, true)) { - // Set permissions on homedir. Parent directories are created - // with 0777, homedir is set to 0700. - chmod($this->_homedir, 0700); - } else { - throw new Crypt_GPG_FileException( - 'The \'homedir\' "' . $this->_homedir . '" is not ' . - 'readable or does not exist and cannot be created. This ' . - 'can happen if \'homedir\' is not specified in the ' . - 'Crypt_GPG options, Crypt_GPG is run as the web user, ' . - 'and the web user has no home directory.', - 0, - $this->_homedir - ); - } - } - - // check homedir permissions (See Bug #19833) - if (!is_executable($this->_homedir)) { - throw new Crypt_GPG_FileException( - 'The \'homedir\' "' . $this->_homedir . '" is not enterable ' . - 'by the current user. Please check the permissions on your ' . - 'homedir and make sure the current user can both enter and ' . - 'write to the directory.', - 0, - $this->_homedir - ); - } - if (!is_writeable($this->_homedir)) { - throw new Crypt_GPG_FileException( - 'The \'homedir\' "' . $this->_homedir . '" is not writable ' . - 'by the current user. Please check the permissions on your ' . - 'homedir and make sure the current user can both enter and ' . - 'write to the directory.', - 0, - $this->_homedir - ); - } - - // get binary - if (array_key_exists('binary', $options)) { - $this->_binary = (string)$options['binary']; - } elseif (array_key_exists('gpgBinary', $options)) { - // deprecated alias - $this->_binary = (string)$options['gpgBinary']; - } else { - $this->_binary = $this->_getBinary(); - } - - if ($this->_binary == '' || !is_executable($this->_binary)) { - throw new PEAR_Exception( - 'GPG binary not found. If you are sure the GPG binary is ' . - 'installed, please specify the location of the GPG binary ' . - 'using the \'binary\' driver option.' - ); - } - - // get agent - if (array_key_exists('agent', $options)) { - $this->_agent = (string)$options['agent']; - } else { - $this->_agent = $this->_getAgent(); - } - - if ($this->_agent == '' || !is_executable($this->_agent)) { - throw new PEAR_Exception( - 'gpg-agent binary not found. If you are sure the gpg-agent ' . - 'is installed, please specify the location of the gpg-agent ' . - 'binary using the \'agent\' driver option.' - ); - } - - /* - * Note: - * - * Normally, GnuPG expects keyrings to be in the homedir and expects - * to be able to write temporary files in the homedir. Sometimes, - * keyrings are not in the homedir, or location of the keyrings does - * not allow writing temporary files. In this case, the homedir - * option by itself is not enough to specify the keyrings because GnuPG - * can not write required temporary files. Additional options are - * provided so you can specify the location of the keyrings separately - * from the homedir. - */ - - // get public keyring - if (array_key_exists('publicKeyring', $options)) { - $this->_publicKeyring = (string)$options['publicKeyring']; - if (!is_readable($this->_publicKeyring)) { - throw new Crypt_GPG_FileException('The \'publicKeyring\' "' . - $this->_publicKeyring . '" does not exist or is ' . - 'not readable. Check the location and ensure the file ' . - 'permissions are correct.', 0, $this->_publicKeyring); - } - } - - // get private keyring - if (array_key_exists('privateKeyring', $options)) { - $this->_privateKeyring = (string)$options['privateKeyring']; - if (!is_readable($this->_privateKeyring)) { - throw new Crypt_GPG_FileException('The \'privateKeyring\' "' . - $this->_privateKeyring . '" does not exist or is ' . - 'not readable. Check the location and ensure the file ' . - 'permissions are correct.', 0, $this->_privateKeyring); - } - } - - // get trust database - if (array_key_exists('trustDb', $options)) { - $this->_trustDb = (string)$options['trustDb']; - if (!is_readable($this->_trustDb)) { - throw new Crypt_GPG_FileException('The \'trustDb\' "' . - $this->_trustDb . '" does not exist or is not readable. ' . - 'Check the location and ensure the file permissions are ' . - 'correct.', 0, $this->_trustDb); - } - } - - if (array_key_exists('debug', $options)) { - $this->_debug = (boolean)$options['debug']; - } - } - - // }}} - // {{{ __destruct() - - /** - * Closes open GPG subprocesses when this object is destroyed - * - * Subprocesses should never be left open by this class unless there is - * an unknown error and unexpected script termination occurs. - */ - public function __destruct() - { - $this->_closeSubprocess(); - } - - // }}} - // {{{ addErrorHandler() - - /** - * Adds an error handler method - * - * The method is run every time a new error line is received from the GPG - * subprocess. The handler method must accept the error line to be handled - * as its first parameter. - * - * @param callback $callback the callback method to use. - * @param array $args optional. Additional arguments to pass as - * parameters to the callback method. - * - * @return void - */ - public function addErrorHandler($callback, array $args = array()) - { - $this->_errorHandlers[] = array( - 'callback' => $callback, - 'args' => $args - ); - } - - // }}} - // {{{ addStatusHandler() - - /** - * Adds a status handler method - * - * The method is run every time a new status line is received from the - * GPG subprocess. The handler method must accept the status line to be - * handled as its first parameter. - * - * @param callback $callback the callback method to use. - * @param array $args optional. Additional arguments to pass as - * parameters to the callback method. - * - * @return void - */ - public function addStatusHandler($callback, array $args = array()) - { - $this->_statusHandlers[] = array( - 'callback' => $callback, - 'args' => $args - ); - } - - // }}} - // {{{ sendCommand() - - /** - * Sends a command to the GPG subprocess over the command file-descriptor - * pipe - * - * @param string $command the command to send. - * - * @return void - * - * @sensitive $command - */ - public function sendCommand($command) - { - if (array_key_exists(self::FD_COMMAND, $this->_openPipes)) { - $this->_commandBuffer .= $command . PHP_EOL; - } - } - - // }}} - // {{{ reset() - - /** - * Resets the GPG engine, preparing it for a new operation - * - * @return void - * - * @see Crypt_GPG_Engine::run() - * @see Crypt_GPG_Engine::setOperation() - */ - public function reset() - { - $this->_operation = ''; - $this->_arguments = array(); - $this->_input = null; - $this->_message = null; - $this->_output = ''; - $this->_errorCode = Crypt_GPG::ERROR_NONE; - $this->_needPassphrase = 0; - $this->_commandBuffer = ''; - - $this->_statusHandlers = array(); - $this->_errorHandlers = array(); - - $this->addStatusHandler(array($this, '_handleErrorStatus')); - $this->addErrorHandler(array($this, '_handleErrorError')); - - if ($this->_debug) { - $this->addStatusHandler(array($this, '_handleDebugStatus')); - $this->addErrorHandler(array($this, '_handleDebugError')); - } - } - - // }}} - // {{{ run() - - /** - * Runs the current GPG operation - * - * This creates and manages the GPG subprocess. - * - * The operation must be set with {@link Crypt_GPG_Engine::setOperation()} - * before this method is called. - * - * @return void - * - * @throws Crypt_GPG_InvalidOperationException if no operation is specified. - * - * @see Crypt_GPG_Engine::reset() - * @see Crypt_GPG_Engine::setOperation() - */ - public function run() - { - if ($this->_operation === '') { - throw new Crypt_GPG_InvalidOperationException('No GPG operation ' . - 'specified. Use Crypt_GPG_Engine::setOperation() before ' . - 'calling Crypt_GPG_Engine::run().'); - } - - $this->_openSubprocess(); - $this->_process(); - $this->_closeSubprocess(); - } - - // }}} - // {{{ getErrorCode() - - /** - * Gets the error code of the last executed operation - * - * This value is only meaningful after {@link Crypt_GPG_Engine::run()} has - * been executed. - * - * @return integer the error code of the last executed operation. - */ - public function getErrorCode() - { - return $this->_errorCode; - } - - // }}} - // {{{ getErrorFilename() - - /** - * Gets the file related to the error code of the last executed operation - * - * This value is only meaningful after {@link Crypt_GPG_Engine::run()} has - * been executed. If there is no file related to the error, an empty string - * is returned. - * - * @return string the file related to the error code of the last executed - * operation. - */ - public function getErrorFilename() - { - return $this->_errorFilename; - } - - // }}} - // {{{ getErrorKeyId() - - /** - * Gets the key id related to the error code of the last executed operation - * - * This value is only meaningful after {@link Crypt_GPG_Engine::run()} has - * been executed. If there is no key id related to the error, an empty - * string is returned. - * - * @return string the key id related to the error code of the last executed - * operation. - */ - public function getErrorKeyId() - { - return $this->_errorKeyId; - } - - // }}} - // {{{ setInput() - - /** - * Sets the input source for the current GPG operation - * - * @param string|resource &$input either a reference to the string - * containing the input data or an open - * stream resource containing the input - * data. - * - * @return void - */ - public function setInput(&$input) - { - $this->_input =& $input; - } - - // }}} - // {{{ setMessage() - - /** - * Sets the message source for the current GPG operation - * - * Detached signature data should be specified here. - * - * @param string|resource &$message either a reference to the string - * containing the message data or an open - * stream resource containing the message - * data. - * - * @return void - */ - public function setMessage(&$message) - { - $this->_message =& $message; - } - - // }}} - // {{{ setOutput() - - /** - * Sets the output destination for the current GPG operation - * - * @param string|resource &$output either a reference to the string in - * which to store GPG output or an open - * stream resource to which the output data - * should be written. - * - * @return void - */ - public function setOutput(&$output) - { - $this->_output =& $output; - } - - // }}} - // {{{ setOperation() - - /** - * Sets the operation to perform - * - * @param string $operation the operation to perform. This should be one - * of GPG's operations. For example, - * --encrypt, --decrypt, - * --sign, etc. - * @param array $arguments optional. Additional arguments for the GPG - * subprocess. See the GPG manual for specific - * values. - * - * @return void - * - * @see Crypt_GPG_Engine::reset() - * @see Crypt_GPG_Engine::run() - */ - public function setOperation($operation, array $arguments = array()) - { - $this->_operation = $operation; - $this->_arguments = $arguments; - } - - // }}} - // {{{ getVersion() - - /** - * Gets the version of the GnuPG binary - * - * @return string a version number string containing the version of GnuPG - * being used. This value is suitable to use with PHP's - * version_compare() function. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @throws Crypt_GPG_UnsupportedException if the provided binary is not - * GnuPG or if the GnuPG version is less than 1.0.2. - */ - public function getVersion() - { - if ($this->_version == '') { - - $options = array( - 'homedir' => $this->_homedir, - 'binary' => $this->_binary, - 'debug' => $this->_debug - ); - - $engine = new self($options); - $info = ''; - - // Set a garbage version so we do not end up looking up the version - // recursively. - $engine->_version = '1.0.0'; - - $engine->reset(); - $engine->setOutput($info); - $engine->setOperation('--version'); - $engine->run(); - - $code = $this->getErrorCode(); - - if ($code !== Crypt_GPG::ERROR_NONE) { - throw new Crypt_GPG_Exception( - 'Unknown error getting GnuPG version information. Please ' . - 'use the \'debug\' option when creating the Crypt_GPG ' . - 'object, and file a bug report at ' . Crypt_GPG::BUG_URI, - $code); - } - - $matches = array(); - $expression = '#gpg \(GnuPG[A-Za-z0-9/]*?\) (\S+)#'; - - if (preg_match($expression, $info, $matches) === 1) { - $this->_version = $matches[1]; - } else { - throw new Crypt_GPG_Exception( - 'No GnuPG version information provided by the binary "' . - $this->_binary . '". Are you sure it is GnuPG?'); - } - - if (version_compare($this->_version, self::MIN_VERSION, 'lt')) { - throw new Crypt_GPG_Exception( - 'The version of GnuPG being used (' . $this->_version . - ') is not supported by Crypt_GPG. The minimum version ' . - 'required by Crypt_GPG is ' . self::MIN_VERSION); - } - } - - - return $this->_version; - } - - // }}} - // {{{ _handleErrorStatus() - - /** - * Handles error values in the status output from GPG - * - * This method is responsible for setting the - * {@link Crypt_GPG_Engine::$_errorCode}. See doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG distribution} for detailed - * information on GPG's status output. - * - * @param string $line the status line to handle. - * - * @return void - */ - private function _handleErrorStatus($line) - { - $tokens = explode(' ', $line); - switch ($tokens[0]) { - case 'BAD_PASSPHRASE': - $this->_errorCode = Crypt_GPG::ERROR_BAD_PASSPHRASE; - break; - - case 'MISSING_PASSPHRASE': - $this->_errorCode = Crypt_GPG::ERROR_MISSING_PASSPHRASE; - break; - - case 'NODATA': - $this->_errorCode = Crypt_GPG::ERROR_NO_DATA; - break; - - case 'DELETE_PROBLEM': - if ($tokens[1] == '1') { - $this->_errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND; - break; - } elseif ($tokens[1] == '2') { - $this->_errorCode = Crypt_GPG::ERROR_DELETE_PRIVATE_KEY; - break; - } - break; - - case 'IMPORT_RES': - if ($tokens[12] > 0) { - $this->_errorCode = Crypt_GPG::ERROR_DUPLICATE_KEY; - } - break; - - case 'NO_PUBKEY': - case 'NO_SECKEY': - $this->_errorKeyId = $tokens[1]; - $this->_errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND; - break; - - case 'NEED_PASSPHRASE': - $this->_needPassphrase++; - break; - - case 'GOOD_PASSPHRASE': - $this->_needPassphrase--; - break; - - case 'EXPSIG': - case 'EXPKEYSIG': - case 'REVKEYSIG': - case 'BADSIG': - $this->_errorCode = Crypt_GPG::ERROR_BAD_SIGNATURE; - break; - - } - } - - // }}} - // {{{ _handleErrorError() - - /** - * Handles error values in the error output from GPG - * - * This method is responsible for setting the - * {@link Crypt_GPG_Engine::$_errorCode}. - * - * @param string $line the error line to handle. - * - * @return void - */ - private function _handleErrorError($line) - { - if ($this->_errorCode === Crypt_GPG::ERROR_NONE) { - $pattern = '/no valid OpenPGP data found/'; - if (preg_match($pattern, $line) === 1) { - $this->_errorCode = Crypt_GPG::ERROR_NO_DATA; - } - } - - if ($this->_errorCode === Crypt_GPG::ERROR_NONE) { - $pattern = '/No secret key|secret key not available/'; - if (preg_match($pattern, $line) === 1) { - $this->_errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND; - } - } - - if ($this->_errorCode === Crypt_GPG::ERROR_NONE) { - $pattern = '/No public key|public key not found/'; - if (preg_match($pattern, $line) === 1) { - $this->_errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND; - } - } - - if ($this->_errorCode === Crypt_GPG::ERROR_NONE) { - $matches = array(); - $pattern = '/can\'t (?:access|open) `(.*?)\'/'; - if (preg_match($pattern, $line, $matches) === 1) { - $this->_errorFilename = $matches[1]; - $this->_errorCode = Crypt_GPG::ERROR_FILE_PERMISSIONS; - } - } - } - - // }}} - // {{{ _handleDebugStatus() - - /** - * Displays debug output for status lines - * - * @param string $line the status line to handle. - * - * @return void - */ - private function _handleDebugStatus($line) - { - $this->_debug('STATUS: ' . $line); - } - - // }}} - // {{{ _handleDebugError() - - /** - * Displays debug output for error lines - * - * @param string $line the error line to handle. - * - * @return void - */ - private function _handleDebugError($line) - { - $this->_debug('ERROR: ' . $line); - } - - // }}} - // {{{ _process() - - /** - * Performs internal streaming operations for the subprocess using either - * strings or streams as input / output points - * - * This is the main I/O loop for streaming to and from the GPG subprocess. - * - * The implementation of this method is verbose mainly for performance - * reasons. Adding streams to a lookup array and looping the array inside - * the main I/O loop would be siginficantly slower for large streams. - * - * @return void - * - * @throws Crypt_GPG_Exception if there is an error selecting streams for - * reading or writing. If this occurs, please file a bug report at - * http://pear.php.net/bugs/report.php?package=Crypt_GPG. - */ - private function _process() - { - $this->_debug('BEGIN PROCESSING'); - - $this->_commandBuffer = ''; // buffers input to GPG - $messageBuffer = ''; // buffers input to GPG - $inputBuffer = ''; // buffers input to GPG - $outputBuffer = ''; // buffers output from GPG - $statusBuffer = ''; // buffers output from GPG - $errorBuffer = ''; // buffers output from GPG - $inputComplete = false; // input stream is completely buffered - $messageComplete = false; // message stream is completely buffered - - if (is_string($this->_input)) { - $inputBuffer = $this->_input; - $inputComplete = true; - } - - if (is_string($this->_message)) { - $messageBuffer = $this->_message; - $messageComplete = true; - } - - if (is_string($this->_output)) { - $outputBuffer =& $this->_output; - } - - // convenience variables - $fdInput = $this->_pipes[self::FD_INPUT]; - $fdOutput = $this->_pipes[self::FD_OUTPUT]; - $fdError = $this->_pipes[self::FD_ERROR]; - $fdStatus = $this->_pipes[self::FD_STATUS]; - $fdCommand = $this->_pipes[self::FD_COMMAND]; - $fdMessage = $this->_pipes[self::FD_MESSAGE]; - - // select loop delay in milliseconds - $delay = 0; - - while (true) { - - $inputStreams = array(); - $outputStreams = array(); - $exceptionStreams = array(); - - // set up input streams - if (is_resource($this->_input) && !$inputComplete) { - if (feof($this->_input)) { - $inputComplete = true; - } else { - $inputStreams[] = $this->_input; - } - } - - // close GPG input pipe if there is no more data - if ($inputBuffer == '' && $inputComplete) { - $this->_debug('=> closing GPG input pipe'); - $this->_closePipe(self::FD_INPUT); - } - - if (is_resource($this->_message) && !$messageComplete) { - if (feof($this->_message)) { - $messageComplete = true; - } else { - $inputStreams[] = $this->_message; - } - } - - // close GPG message pipe if there is no more data - if ($messageBuffer == '' && $messageComplete) { - $this->_debug('=> closing GPG message pipe'); - $this->_closePipe(self::FD_MESSAGE); - } - - if (!feof($fdOutput)) { - $inputStreams[] = $fdOutput; - } - - if (!feof($fdStatus)) { - $inputStreams[] = $fdStatus; - } - - if (!feof($fdError)) { - $inputStreams[] = $fdError; - } - - // set up output streams - if ($outputBuffer != '' && is_resource($this->_output)) { - $outputStreams[] = $this->_output; - } - - if ($this->_commandBuffer != '' && is_resource($fdCommand)) { - $outputStreams[] = $fdCommand; - } - - if ($messageBuffer != '' && is_resource($fdMessage)) { - $outputStreams[] = $fdMessage; - } - - if ($inputBuffer != '' && is_resource($fdInput)) { - $outputStreams[] = $fdInput; - } - - // no streams left to read or write, we're all done - if (count($inputStreams) === 0 && count($outputStreams) === 0) { - break; - } - - $this->_debug('selecting streams'); - - $ready = stream_select( - $inputStreams, - $outputStreams, - $exceptionStreams, - null - ); - - $this->_debug('=> got ' . $ready); - - if ($ready === false) { - throw new Crypt_GPG_Exception( - 'Error selecting stream for communication with GPG ' . - 'subprocess. Please file a bug report at: ' . - 'http://pear.php.net/bugs/report.php?package=Crypt_GPG'); - } - - if ($ready === 0) { - throw new Crypt_GPG_Exception( - 'stream_select() returned 0. This can not happen! Please ' . - 'file a bug report at: ' . - 'http://pear.php.net/bugs/report.php?package=Crypt_GPG'); - } - - // write input (to GPG) - if (in_array($fdInput, $outputStreams, true)) { - $this->_debug('GPG is ready for input'); - - $chunk = Crypt_GPG_ByteUtils::substr( - $inputBuffer, - 0, - self::CHUNK_SIZE - ); - - $length = Crypt_GPG_ByteUtils::strlen($chunk); - - $this->_debug( - '=> about to write ' . $length . ' bytes to GPG input' - ); - - $length = fwrite($fdInput, $chunk, $length); - if ($length === 0) { - // If we wrote 0 bytes it was either EAGAIN or EPIPE. Since - // the pipe was seleted for writing, we assume it was EPIPE. - // There's no way to get the actual erorr code in PHP. See - // PHP Bug #39598. https://bugs.php.net/bug.php?id=39598 - $this->_debug('=> broken pipe on GPG input'); - $this->_debug('=> closing pipe GPG input'); - $this->_closePipe(self::FD_INPUT); - } else { - $this->_debug('=> wrote ' . $length . ' bytes'); - $inputBuffer = Crypt_GPG_ByteUtils::substr( - $inputBuffer, - $length - ); - } - } - - // read input (from PHP stream) - if (in_array($this->_input, $inputStreams, true)) { - $this->_debug('input stream is ready for reading'); - $this->_debug( - '=> about to read ' . self::CHUNK_SIZE . - ' bytes from input stream' - ); - - $chunk = fread($this->_input, self::CHUNK_SIZE); - $length = Crypt_GPG_ByteUtils::strlen($chunk); - $inputBuffer .= $chunk; - - $this->_debug('=> read ' . $length . ' bytes'); - } - - // write message (to GPG) - if (in_array($fdMessage, $outputStreams, true)) { - $this->_debug('GPG is ready for message data'); - - $chunk = Crypt_GPG_ByteUtils::substr( - $messageBuffer, - 0, - self::CHUNK_SIZE - ); - - $length = Crypt_GPG_ByteUtils::strlen($chunk); - - $this->_debug( - '=> about to write ' . $length . ' bytes to GPG message' - ); - - $length = fwrite($fdMessage, $chunk, $length); - if ($length === 0) { - // If we wrote 0 bytes it was either EAGAIN or EPIPE. Since - // the pipe was seleted for writing, we assume it was EPIPE. - // There's no way to get the actual erorr code in PHP. See - // PHP Bug #39598. https://bugs.php.net/bug.php?id=39598 - $this->_debug('=> broken pipe on GPG message'); - $this->_debug('=> closing pipe GPG message'); - $this->_closePipe(self::FD_MESSAGE); - } else { - $this->_debug('=> wrote ' . $length . ' bytes'); - $messageBuffer = Crypt_GPG_ByteUtils::substr( - $messageBuffer, - $length - ); - } - } - - // read message (from PHP stream) - if (in_array($this->_message, $inputStreams, true)) { - $this->_debug('message stream is ready for reading'); - $this->_debug( - '=> about to read ' . self::CHUNK_SIZE . - ' bytes from message stream' - ); - - $chunk = fread($this->_message, self::CHUNK_SIZE); - $length = Crypt_GPG_ByteUtils::strlen($chunk); - $messageBuffer .= $chunk; - - $this->_debug('=> read ' . $length . ' bytes'); - } - - // read output (from GPG) - if (in_array($fdOutput, $inputStreams, true)) { - $this->_debug('GPG output stream ready for reading'); - $this->_debug( - '=> about to read ' . self::CHUNK_SIZE . - ' bytes from GPG output' - ); - - $chunk = fread($fdOutput, self::CHUNK_SIZE); - $length = Crypt_GPG_ByteUtils::strlen($chunk); - $outputBuffer .= $chunk; - - $this->_debug('=> read ' . $length . ' bytes'); - } - - // write output (to PHP stream) - if (in_array($this->_output, $outputStreams, true)) { - $this->_debug('output stream is ready for data'); - - $chunk = Crypt_GPG_ByteUtils::substr( - $outputBuffer, - 0, - self::CHUNK_SIZE - ); - - $length = Crypt_GPG_ByteUtils::strlen($chunk); - - $this->_debug( - '=> about to write ' . $length . ' bytes to output stream' - ); - - $length = fwrite($this->_output, $chunk, $length); - - $this->_debug('=> wrote ' . $length . ' bytes'); - - $outputBuffer = Crypt_GPG_ByteUtils::substr( - $outputBuffer, - $length - ); - } - - // read error (from GPG) - if (in_array($fdError, $inputStreams, true)) { - $this->_debug('GPG error stream ready for reading'); - $this->_debug( - '=> about to read ' . self::CHUNK_SIZE . - ' bytes from GPG error' - ); - - $chunk = fread($fdError, self::CHUNK_SIZE); - $length = Crypt_GPG_ByteUtils::strlen($chunk); - $errorBuffer .= $chunk; - - $this->_debug('=> read ' . $length . ' bytes'); - - // pass lines to error handlers - while (($pos = strpos($errorBuffer, PHP_EOL)) !== false) { - $line = Crypt_GPG_ByteUtils::substr($errorBuffer, 0, $pos); - foreach ($this->_errorHandlers as $handler) { - array_unshift($handler['args'], $line); - call_user_func_array( - $handler['callback'], - $handler['args'] - ); - - array_shift($handler['args']); - } - $errorBuffer = Crypt_GPG_ByteUtils::substr( - $errorBuffer, - $pos + Crypt_GPG_ByteUtils::strlen(PHP_EOL) - ); - } - } - - // read status (from GPG) - if (in_array($fdStatus, $inputStreams, true)) { - $this->_debug('GPG status stream ready for reading'); - $this->_debug( - '=> about to read ' . self::CHUNK_SIZE . - ' bytes from GPG status' - ); - - $chunk = fread($fdStatus, self::CHUNK_SIZE); - $length = Crypt_GPG_ByteUtils::strlen($chunk); - $statusBuffer .= $chunk; - - $this->_debug('=> read ' . $length . ' bytes'); - - // pass lines to status handlers - while (($pos = strpos($statusBuffer, PHP_EOL)) !== false) { - $line = Crypt_GPG_ByteUtils::substr($statusBuffer, 0, $pos); - // only pass lines beginning with magic prefix - if (Crypt_GPG_ByteUtils::substr($line, 0, 9) == '[GNUPG:] ') { - $line = Crypt_GPG_ByteUtils::substr($line, 9); - foreach ($this->_statusHandlers as $handler) { - array_unshift($handler['args'], $line); - call_user_func_array( - $handler['callback'], - $handler['args'] - ); - - array_shift($handler['args']); - } - } - $statusBuffer = Crypt_GPG_ByteUtils::substr( - $statusBuffer, - $pos + Crypt_GPG_ByteUtils::strlen(PHP_EOL) - ); - } - } - - // write command (to GPG) - if (in_array($fdCommand, $outputStreams, true)) { - $this->_debug('GPG is ready for command data'); - - // send commands - $chunk = Crypt_GPG_ByteUtils::substr( - $this->_commandBuffer, - 0, - self::CHUNK_SIZE - ); - - $length = Crypt_GPG_ByteUtils::strlen($chunk); - - $this->_debug( - '=> about to write ' . $length . ' bytes to GPG command' - ); - - $length = fwrite($fdCommand, $chunk, $length); - if ($length === 0) { - // If we wrote 0 bytes it was either EAGAIN or EPIPE. Since - // the pipe was seleted for writing, we assume it was EPIPE. - // There's no way to get the actual erorr code in PHP. See - // PHP Bug #39598. https://bugs.php.net/bug.php?id=39598 - $this->_debug('=> broken pipe on GPG command'); - $this->_debug('=> closing pipe GPG command'); - $this->_closePipe(self::FD_COMMAND); - } else { - $this->_debug('=> wrote ' . $length); - $this->_commandBuffer = Crypt_GPG_ByteUtils::substr( - $this->_commandBuffer, - $length - ); - } - } - - if (count($outputStreams) === 0 || count($inputStreams) === 0) { - // we have an I/O imbalance, increase the select loop delay - // to smooth things out - $delay += 10; - } else { - // things are running smoothly, decrease the delay - $delay -= 8; - $delay = max(0, $delay); - } - - if ($delay > 0) { - usleep($delay); - } - - } // end loop while streams are open - - $this->_debug('END PROCESSING'); - } - - // }}} - // {{{ _openSubprocess() - - /** - * Opens an internal GPG subprocess for the current operation - * - * Opens a GPG subprocess, then connects the subprocess to some pipes. Sets - * the private class property {@link Crypt_GPG_Engine::$_process} to - * the new subprocess. - * - * @return void - * - * @throws Crypt_GPG_OpenSubprocessException if the subprocess could not be - * opened. - * - * @see Crypt_GPG_Engine::setOperation() - * @see Crypt_GPG_Engine::_closeSubprocess() - * @see Crypt_GPG_Engine::$_process - */ - private function _openSubprocess() - { - $version = $this->getVersion(); - - // Binary operations will not work on Windows with PHP < 5.2.6. This is - // in case stream_select() ever works on Windows. - $rb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'r' : 'rb'; - $wb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'w' : 'wb'; - - $env = $_ENV; - - // Newer versions of GnuPG return localized results. Crypt_GPG only - // works with English, so set the locale to 'C' for the subprocess. - $env['LC_ALL'] = 'C'; - - // If using GnuPG 2.x start the gpg-agent - if (version_compare($version, '2.0.0', 'ge')) { - $agentCommandLine = $this->_agent; - - $agentArguments = array( - '--options /dev/null', // ignore any saved options - '--csh', // output is easier to parse - '--keep-display', // prevent passing --display to pinentry - '--no-grab', - '--ignore-cache-for-signing', - '--pinentry-touch-file /dev/null', - '--disable-scdaemon', - '--no-use-standard-socket', - '--pinentry-program ' . escapeshellarg($this->_getPinEntry()) - ); - - if ($this->_homedir) { - $agentArguments[] = '--homedir ' . - escapeshellarg($this->_homedir); - } - - - $agentCommandLine .= ' ' . implode(' ', $agentArguments) - . ' --daemon'; - - $agentDescriptorSpec = array( - self::FD_INPUT => array('pipe', $rb), // stdin - self::FD_OUTPUT => array('pipe', $wb), // stdout - self::FD_ERROR => array('pipe', $wb) // stderr - ); - - $this->_debug('OPENING GPG-AGENT SUBPROCESS WITH THE FOLLOWING COMMAND:'); - $this->_debug($agentCommandLine); - - $this->_agentProcess = proc_open( - $agentCommandLine, - $agentDescriptorSpec, - $this->_agentPipes, - null, - $env, - array('binary_pipes' => true) - ); - - if (!is_resource($this->_agentProcess)) { - throw new Crypt_GPG_OpenSubprocessException( - 'Unable to open gpg-agent subprocess.', - 0, - $agentCommandLine - ); - } - - // Get GPG_AGENT_INFO and set environment variable for gpg process. - // This is a blocking read, but is only 1 line. - $agentInfo = fread( - $this->_agentPipes[self::FD_OUTPUT], - self::CHUNK_SIZE - ); - - $agentInfo = explode(' ', $agentInfo, 3); - $this->_agentInfo = $agentInfo[2]; - $env['GPG_AGENT_INFO'] = $this->_agentInfo; - - // gpg-agent daemon is started, we can close the launching process - $this->_closeAgentLaunchProcess(); - } - - $commandLine = $this->_binary; - - $defaultArguments = array( - '--status-fd ' . escapeshellarg(self::FD_STATUS), - '--command-fd ' . escapeshellarg(self::FD_COMMAND), - '--no-secmem-warning', - '--no-tty', - '--no-default-keyring', // ignored if keying files are not specified - '--no-options' // prevent creation of ~/.gnupg directory - ); - - if (version_compare($version, '1.0.7', 'ge')) { - if (version_compare($version, '2.0.0', 'lt')) { - $defaultArguments[] = '--no-use-agent'; - } - $defaultArguments[] = '--no-permission-warning'; - } - - if (version_compare($version, '1.4.2', 'ge')) { - $defaultArguments[] = '--exit-on-status-write-error'; - } - - if (version_compare($version, '1.3.2', 'ge')) { - $defaultArguments[] = '--trust-model always'; - } else { - $defaultArguments[] = '--always-trust'; - } - - $arguments = array_merge($defaultArguments, $this->_arguments); - - if ($this->_homedir) { - $arguments[] = '--homedir ' . escapeshellarg($this->_homedir); - - // the random seed file makes subsequent actions faster so only - // disable it if we have to. - if (!is_writeable($this->_homedir)) { - $arguments[] = '--no-random-seed-file'; - } - } - - if ($this->_publicKeyring) { - $arguments[] = '--keyring ' . escapeshellarg($this->_publicKeyring); - } - - if ($this->_privateKeyring) { - $arguments[] = '--secret-keyring ' . - escapeshellarg($this->_privateKeyring); - } - - if ($this->_trustDb) { - $arguments[] = '--trustdb-name ' . escapeshellarg($this->_trustDb); - } - - $commandLine .= ' ' . implode(' ', $arguments) . ' ' . - $this->_operation; - - $descriptorSpec = array( - self::FD_INPUT => array('pipe', $rb), // stdin - self::FD_OUTPUT => array('pipe', $wb), // stdout - self::FD_ERROR => array('pipe', $wb), // stderr - self::FD_STATUS => array('pipe', $wb), // status - self::FD_COMMAND => array('pipe', $rb), // command - self::FD_MESSAGE => array('pipe', $rb) // message - ); - - $this->_debug('OPENING GPG SUBPROCESS WITH THE FOLLOWING COMMAND:'); - $this->_debug($commandLine); - - $this->_process = proc_open( - $commandLine, - $descriptorSpec, - $this->_pipes, - null, - $env, - array('binary_pipes' => true) - ); - - if (!is_resource($this->_process)) { - throw new Crypt_GPG_OpenSubprocessException( - 'Unable to open GPG subprocess.', 0, $commandLine); - } - - // Set streams as non-blocking. See Bug #18618. - foreach ($this->_pipes as $pipe) { - stream_set_blocking($pipe, 0); - } - - $this->_openPipes = $this->_pipes; - $this->_errorCode = Crypt_GPG::ERROR_NONE; - } - - // }}} - // {{{ _closeSubprocess() - - /** - * Closes a the internal GPG subprocess - * - * Closes the internal GPG subprocess. Sets the private class property - * {@link Crypt_GPG_Engine::$_process} to null. - * - * @return void - * - * @see Crypt_GPG_Engine::_openSubprocess() - * @see Crypt_GPG_Engine::$_process - */ - private function _closeSubprocess() - { - // clear PINs from environment if they were set - $_ENV['PINENTRY_USER_DATA'] = null; - - if (is_resource($this->_process)) { - $this->_debug('CLOSING GPG SUBPROCESS'); - - // close remaining open pipes - foreach (array_keys($this->_openPipes) as $pipeNumber) { - $this->_closePipe($pipeNumber); - } - - $exitCode = proc_close($this->_process); - - if ($exitCode != 0) { - $this->_debug( - '=> subprocess returned an unexpected exit code: ' . - $exitCode - ); - - if ($this->_errorCode === Crypt_GPG::ERROR_NONE) { - if ($this->_needPassphrase > 0) { - $this->_errorCode = Crypt_GPG::ERROR_MISSING_PASSPHRASE; - } else { - $this->_errorCode = Crypt_GPG::ERROR_UNKNOWN; - } - } - } - - $this->_process = null; - $this->_pipes = array(); - } - - $this->_closeAgentLaunchProcess(); - - if ($this->_agentInfo !== null) { - $this->_debug('STOPPING GPG-AGENT DAEMON'); - - $parts = explode(':', $this->_agentInfo, 3); - $pid = $parts[1]; - $process = new Crypt_GPG_ProcessControl($pid); - - // terminate agent daemon - $process->terminate(); - - while ($process->isRunning()) { - usleep(10000); // 10 ms - $process->terminate(); - } - - $this->_agentInfo = null; - - $this->_debug('GPG-AGENT DAEMON STOPPED'); - } - } - - // }}} - // {{ _closeAgentLaunchProcess() - - private function _closeAgentLaunchProcess() - { - if (is_resource($this->_agentProcess)) { - $this->_debug('CLOSING GPG-AGENT LAUNCH PROCESS'); - - // close agent pipes - foreach ($this->_agentPipes as $pipe) { - fflush($pipe); - fclose($pipe); - } - - // close agent launching process - proc_close($this->_agentProcess); - - $this->_agentProcess = null; - $this->_agentPipes = array(); - - $this->_debug('GPG-AGENT LAUNCH PROCESS CLOSED'); - } - } - - // }} - // {{{ _closePipe() - - /** - * Closes an opened pipe used to communicate with the GPG subprocess - * - * If the pipe is already closed, it is ignored. If the pipe is open, it - * is flushed and then closed. - * - * @param integer $pipeNumber the file descriptor number of the pipe to - * close. - * - * @return void - */ - private function _closePipe($pipeNumber) - { - $pipeNumber = intval($pipeNumber); - if (array_key_exists($pipeNumber, $this->_openPipes)) { - fflush($this->_openPipes[$pipeNumber]); - fclose($this->_openPipes[$pipeNumber]); - unset($this->_openPipes[$pipeNumber]); - } - } - - // }}} - // {{{ _getBinary() - - /** - * Gets the name of the GPG binary for the current operating system - * - * This method is called if the 'binary' option is not - * specified when creating this driver. - * - * @return string the name of the GPG binary for the current operating - * system. If no suitable binary could be found, an empty - * string is returned. - */ - private function _getBinary() - { - $binary = ''; - - if ($this->_isDarwin) { - $binaryFiles = array( - '/opt/local/bin/gpg', // MacPorts - '/usr/local/bin/gpg', // Mac GPG - '/sw/bin/gpg', // Fink - '/usr/bin/gpg' - ); - } else { - $binaryFiles = array( - '/usr/bin/gpg', - '/usr/local/bin/gpg' - ); - } - - foreach ($binaryFiles as $binaryFile) { - if (is_executable($binaryFile)) { - $binary = $binaryFile; - break; - } - } - - return $binary; - } - - // }}} - // {{ _getAgent() - - private function _getAgent() - { - $agent = ''; - - if ($this->_isDarwin) { - $agentFiles = array( - '/opt/local/bin/gpg-agent', // MacPorts - '/usr/local/bin/gpg-agent', // Mac GPG - '/sw/bin/gpg-agent', // Fink - '/usr/bin/gpg-agent' - ); - } else { - $agentFiles = array( - '/usr/bin/gpg-agent', - '/usr/local/bin/gpg-agent' - ); - } - - foreach ($agentFiles as $agentFile) { - if (is_executable($agentFile)) { - $agent = $agentFile; - break; - } - } - - return $agent; - } - - // }} - // {{ _getPinEntry() - - private function _getPinEntry() - { - // Check if we're running directly from git or if we're using a - // PEAR-packaged version - $pinEntry = '@bin-dir@' . DIRECTORY_SEPARATOR . 'crypt-gpg-pinentry'; - - if ($pinEntry[0] === '@') { - $pinEntry = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' - . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'scripts' - . DIRECTORY_SEPARATOR . 'crypt-gpg-pinentry'; - } - - return $pinEntry; - } - - // }} - // {{{ _debug() - - /** - * Displays debug text if debugging is turned on - * - * Debugging text is prepended with a debug identifier and echoed to stdout. - * - * @param string $text the debugging text to display. - * - * @return void - */ - private function _debug($text) - { - if ($this->_debug) { - if (php_sapi_name() === 'cli') { - foreach (explode(PHP_EOL, $text) as $line) { - echo "Crypt_GPG DEBUG: ", $line, PHP_EOL; - } - } else { - // running on a web server, format debug output nicely - foreach (explode(PHP_EOL, $text) as $line) { - echo "Crypt_GPG DEBUG: ", $line, - '
', PHP_EOL; - } - } - } - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/Exceptions.php b/program/lib/Crypt/GPG/Exceptions.php deleted file mode 100644 index 0ca917db6..000000000 --- a/program/lib/Crypt/GPG/Exceptions.php +++ /dev/null @@ -1,598 +0,0 @@ - - * @author Michael Gauthier - * @copyright 2005-2011 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -/** - * PEAR Exception handler and base class - */ -require_once 'PEAR/Exception.php'; - -// {{{ class Crypt_GPG_Exception - -/** - * An exception thrown by the Crypt_GPG package - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2005 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_Exception extends PEAR_Exception -{ -} - -// }}} -// {{{ class Crypt_GPG_FileException - -/** - * An exception thrown when a file is used in ways it cannot be used - * - * For example, if an output file is specified and the file is not writeable, or - * if an input file is specified and the file is not readable, this exception - * is thrown. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2007-2008 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_FileException extends Crypt_GPG_Exception -{ - // {{{ private class properties - - /** - * The name of the file that caused this exception - * - * @var string - */ - private $_filename = ''; - - // }}} - // {{{ __construct() - - /** - * Creates a new Crypt_GPG_FileException - * - * @param string $message an error message. - * @param integer $code a user defined error code. - * @param string $filename the name of the file that caused this exception. - */ - public function __construct($message, $code = 0, $filename = '') - { - $this->_filename = $filename; - parent::__construct($message, $code); - } - - // }}} - // {{{ getFilename() - - /** - * Returns the filename of the file that caused this exception - * - * @return string the filename of the file that caused this exception. - * - * @see Crypt_GPG_FileException::$_filename - */ - public function getFilename() - { - return $this->_filename; - } - - // }}} -} - -// }}} -// {{{ class Crypt_GPG_OpenSubprocessException - -/** - * An exception thrown when the GPG subprocess cannot be opened - * - * This exception is thrown when the {@link Crypt_GPG_Engine} tries to open a - * new subprocess and fails. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2005 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_OpenSubprocessException extends Crypt_GPG_Exception -{ - // {{{ private class properties - - /** - * The command used to try to open the subprocess - * - * @var string - */ - private $_command = ''; - - // }}} - // {{{ __construct() - - /** - * Creates a new Crypt_GPG_OpenSubprocessException - * - * @param string $message an error message. - * @param integer $code a user defined error code. - * @param string $command the command that was called to open the - * new subprocess. - * - * @see Crypt_GPG::_openSubprocess() - */ - public function __construct($message, $code = 0, $command = '') - { - $this->_command = $command; - parent::__construct($message, $code); - } - - // }}} - // {{{ getCommand() - - /** - * Returns the contents of the internal _command property - * - * @return string the command used to open the subprocess. - * - * @see Crypt_GPG_OpenSubprocessException::$_command - */ - public function getCommand() - { - return $this->_command; - } - - // }}} -} - -// }}} -// {{{ class Crypt_GPG_InvalidOperationException - -/** - * An exception thrown when an invalid GPG operation is attempted - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2008 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_InvalidOperationException extends Crypt_GPG_Exception -{ - // {{{ private class properties - - /** - * The attempted operation - * - * @var string - */ - private $_operation = ''; - - // }}} - // {{{ __construct() - - /** - * Creates a new Crypt_GPG_OpenSubprocessException - * - * @param string $message an error message. - * @param integer $code a user defined error code. - * @param string $operation the operation. - */ - public function __construct($message, $code = 0, $operation = '') - { - $this->_operation = $operation; - parent::__construct($message, $code); - } - - // }}} - // {{{ getOperation() - - /** - * Returns the contents of the internal _operation property - * - * @return string the attempted operation. - * - * @see Crypt_GPG_InvalidOperationException::$_operation - */ - public function getOperation() - { - return $this->_operation; - } - - // }}} -} - -// }}} -// {{{ class Crypt_GPG_KeyNotFoundException - -/** - * An exception thrown when Crypt_GPG fails to find the key for various - * operations - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2005 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_KeyNotFoundException extends Crypt_GPG_Exception -{ - // {{{ private class properties - - /** - * The key identifier that was searched for - * - * @var string - */ - private $_keyId = ''; - - // }}} - // {{{ __construct() - - /** - * Creates a new Crypt_GPG_KeyNotFoundException - * - * @param string $message an error message. - * @param integer $code a user defined error code. - * @param string $keyId the key identifier of the key. - */ - public function __construct($message, $code = 0, $keyId= '') - { - $this->_keyId = $keyId; - parent::__construct($message, $code); - } - - // }}} - // {{{ getKeyId() - - /** - * Gets the key identifier of the key that was not found - * - * @return string the key identifier of the key that was not found. - */ - public function getKeyId() - { - return $this->_keyId; - } - - // }}} -} - -// }}} -// {{{ class Crypt_GPG_NoDataException - -/** - * An exception thrown when Crypt_GPG cannot find valid data for various - * operations - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2006 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_NoDataException extends Crypt_GPG_Exception -{ -} - -// }}} -// {{{ class Crypt_GPG_BadPassphraseException - -/** - * An exception thrown when a required passphrase is incorrect or missing - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2006-2008 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_BadPassphraseException extends Crypt_GPG_Exception -{ - // {{{ private class properties - - /** - * Keys for which the passhprase is missing - * - * This contains primary user ids indexed by sub-key id. - * - * @var array - */ - private $_missingPassphrases = array(); - - /** - * Keys for which the passhprase is incorrect - * - * This contains primary user ids indexed by sub-key id. - * - * @var array - */ - private $_badPassphrases = array(); - - // }}} - // {{{ __construct() - - /** - * Creates a new Crypt_GPG_BadPassphraseException - * - * @param string $message an error message. - * @param integer $code a user defined error code. - * @param string $badPassphrases an array containing user ids of keys - * for which the passphrase is incorrect. - * @param string $missingPassphrases an array containing user ids of keys - * for which the passphrase is missing. - */ - public function __construct($message, $code = 0, - array $badPassphrases = array(), array $missingPassphrases = array() - ) { - $this->_badPassphrases = $badPassphrases; - $this->_missingPassphrases = $missingPassphrases; - - parent::__construct($message, $code); - } - - // }}} - // {{{ getBadPassphrases() - - /** - * Gets keys for which the passhprase is incorrect - * - * @return array an array of keys for which the passphrase is incorrect. - * The array contains primary user ids indexed by the sub-key - * id. - */ - public function getBadPassphrases() - { - return $this->_badPassphrases; - } - - // }}} - // {{{ getMissingPassphrases() - - /** - * Gets keys for which the passhprase is missing - * - * @return array an array of keys for which the passphrase is missing. - * The array contains primary user ids indexed by the sub-key - * id. - */ - public function getMissingPassphrases() - { - return $this->_missingPassphrases; - } - - // }}} -} - -// }}} -// {{{ class Crypt_GPG_DeletePrivateKeyException - -/** - * An exception thrown when an attempt is made to delete public key that has an - * associated private key on the keyring - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2008 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_DeletePrivateKeyException extends Crypt_GPG_Exception -{ - // {{{ private class properties - - /** - * The key identifier the deletion attempt was made upon - * - * @var string - */ - private $_keyId = ''; - - // }}} - // {{{ __construct() - - /** - * Creates a new Crypt_GPG_DeletePrivateKeyException - * - * @param string $message an error message. - * @param integer $code a user defined error code. - * @param string $keyId the key identifier of the public key that was - * attempted to delete. - * - * @see Crypt_GPG::deletePublicKey() - */ - public function __construct($message, $code = 0, $keyId = '') - { - $this->_keyId = $keyId; - parent::__construct($message, $code); - } - - // }}} - // {{{ getKeyId() - - /** - * Gets the key identifier of the key that was not found - * - * @return string the key identifier of the key that was not found. - */ - public function getKeyId() - { - return $this->_keyId; - } - - // }}} -} - -// }}} -// {{{ class Crypt_GPG_KeyNotCreatedException - -/** - * An exception thrown when an attempt is made to generate a key and the - * attempt fails - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2011 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_KeyNotCreatedException extends Crypt_GPG_Exception -{ -} - -// }}} -// {{{ class Crypt_GPG_InvalidKeyParamsException - -/** - * An exception thrown when an attempt is made to generate a key and the - * key parameters set on the key generator are invalid - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2011 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_InvalidKeyParamsException extends Crypt_GPG_Exception -{ - // {{{ private class properties - - /** - * The key algorithm - * - * @var integer - */ - private $_algorithm = 0; - - /** - * The key size - * - * @var integer - */ - private $_size = 0; - - /** - * The key usage - * - * @var integer - */ - private $_usage = 0; - - // }}} - // {{{ __construct() - - /** - * Creates a new Crypt_GPG_InvalidKeyParamsException - * - * @param string $message an error message. - * @param integer $code a user defined error code. - * @param string $algorithm the key algorithm. - * @param string $size the key size. - * @param string $usage the key usage. - */ - public function __construct( - $message, - $code = 0, - $algorithm = 0, - $size = 0, - $usage = 0 - ) { - parent::__construct($message, $code); - - $this->_algorithm = $algorithm; - $this->_size = $size; - $this->_usage = $usage; - } - - // }}} - // {{{ getAlgorithm() - - /** - * Gets the key algorithm - * - * @return integer the key algorithm. - */ - public function getAlgorithm() - { - return $this->_algorithm; - } - - // }}} - // {{{ getSize() - - /** - * Gets the key size - * - * @return integer the key size. - */ - public function getSize() - { - return $this->_size; - } - - // }}} - // {{{ getUsage() - - /** - * Gets the key usage - * - * @return integer the key usage. - */ - public function getUsage() - { - return $this->_usage; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/Key.php b/program/lib/Crypt/GPG/Key.php deleted file mode 100644 index 6ecb538bc..000000000 --- a/program/lib/Crypt/GPG/Key.php +++ /dev/null @@ -1,223 +0,0 @@ - - * @copyright 2008-2010 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -/** - * Sub-key class definition - */ -require_once 'Crypt/GPG/SubKey.php'; - -/** - * User id class definition - */ -require_once 'Crypt/GPG/UserId.php'; - -// {{{ class Crypt_GPG_Key - -/** - * A data class for GPG key information - * - * This class is used to store the results of the {@link Crypt_GPG::getKeys()} - * method. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2008-2010 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @see Crypt_GPG::getKeys() - */ -class Crypt_GPG_Key -{ - // {{{ class properties - - /** - * The user ids associated with this key - * - * This is an array of {@link Crypt_GPG_UserId} objects. - * - * @var array - * - * @see Crypt_GPG_Key::addUserId() - * @see Crypt_GPG_Key::getUserIds() - */ - private $_userIds = array(); - - /** - * The subkeys of this key - * - * This is an array of {@link Crypt_GPG_SubKey} objects. - * - * @var array - * - * @see Crypt_GPG_Key::addSubKey() - * @see Crypt_GPG_Key::getSubKeys() - */ - private $_subKeys = array(); - - // }}} - // {{{ getSubKeys() - - /** - * Gets the sub-keys of this key - * - * @return array the sub-keys of this key. - * - * @see Crypt_GPG_Key::addSubKey() - */ - public function getSubKeys() - { - return $this->_subKeys; - } - - // }}} - // {{{ getUserIds() - - /** - * Gets the user ids of this key - * - * @return array the user ids of this key. - * - * @see Crypt_GPG_Key::addUserId() - */ - public function getUserIds() - { - return $this->_userIds; - } - - // }}} - // {{{ getPrimaryKey() - - /** - * Gets the primary sub-key of this key - * - * The primary key is the first added sub-key. - * - * @return Crypt_GPG_SubKey the primary sub-key of this key. - */ - public function getPrimaryKey() - { - $primary_key = null; - if (count($this->_subKeys) > 0) { - $primary_key = $this->_subKeys[0]; - } - return $primary_key; - } - - // }}} - // {{{ canSign() - - /** - * Gets whether or not this key can sign data - * - * This key can sign data if any sub-key of this key can sign data. - * - * @return boolean true if this key can sign data and false if this key - * cannot sign data. - */ - public function canSign() - { - $canSign = false; - foreach ($this->_subKeys as $subKey) { - if ($subKey->canSign()) { - $canSign = true; - break; - } - } - return $canSign; - } - - // }}} - // {{{ canEncrypt() - - /** - * Gets whether or not this key can encrypt data - * - * This key can encrypt data if any sub-key of this key can encrypt data. - * - * @return boolean true if this key can encrypt data and false if this - * key cannot encrypt data. - */ - public function canEncrypt() - { - $canEncrypt = false; - foreach ($this->_subKeys as $subKey) { - if ($subKey->canEncrypt()) { - $canEncrypt = true; - break; - } - } - return $canEncrypt; - } - - // }}} - // {{{ addSubKey() - - /** - * Adds a sub-key to this key - * - * The first added sub-key will be the primary key of this key. - * - * @param Crypt_GPG_SubKey $subKey the sub-key to add. - * - * @return Crypt_GPG_Key the current object, for fluent interface. - */ - public function addSubKey(Crypt_GPG_SubKey $subKey) - { - $this->_subKeys[] = $subKey; - return $this; - } - - // }}} - // {{{ addUserId() - - /** - * Adds a user id to this key - * - * @param Crypt_GPG_UserId $userId the user id to add. - * - * @return Crypt_GPG_Key the current object, for fluent interface. - */ - public function addUserId(Crypt_GPG_UserId $userId) - { - $this->_userIds[] = $userId; - return $this; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/KeyGenerator.php b/program/lib/Crypt/GPG/KeyGenerator.php deleted file mode 100644 index f59c0ee3a..000000000 --- a/program/lib/Crypt/GPG/KeyGenerator.php +++ /dev/null @@ -1,790 +0,0 @@ - - * @copyright 2011-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id:$ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ - -/** - * Base class for GPG methods - */ -require_once 'Crypt/GPGAbstract.php'; - -/** - * Status output handler for key generation - */ -require_once 'Crypt/GPG/KeyGeneratorStatusHandler.php'; - -/** - * Error output handler for key generation - */ -require_once 'Crypt/GPG/KeyGeneratorErrorHandler.php'; - -// {{{ class Crypt_GPG_KeyGenerator - -/** - * GnuPG key generator - * - * This class provides an object oriented interface for generating keys with - * the GNU Privacy Guard (GPG). - * - * Secure key generation requires true random numbers, and as such can be slow. - * If the operating system runs out of entropy, key generation will block until - * more entropy is available. - * - * If quick key generation is important, a hardware entropy generator, or an - * entropy gathering daemon may be installed. For example, administrators of - * Debian systems may want to install the 'randomsound' package. - * - * This class uses the experimental automated key generation support available - * in GnuPG. See doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG distribution} for detailed - * information on the key generation format. - * - * @category Encryption - * @package Crypt_GPG - * @author Nathan Fredrickson - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -class Crypt_GPG_KeyGenerator extends Crypt_GPGAbstract -{ - // {{{ protected properties - - /** - * The expiration date of generated keys - * - * @var integer - * - * @see Crypt_GPG_KeyGenerator::setExpirationDate() - */ - protected $expirationDate = 0; - - /** - * The passphrase of generated keys - * - * @var string - * - * @see Crypt_GPG_KeyGenerator::setPassphrase() - */ - protected $passphrase = ''; - - /** - * The algorithm for generated primary keys - * - * @var integer - * - * @see Crypt_GPG_KeyGenerator::setKeyParams() - */ - protected $keyAlgorithm = Crypt_GPG_SubKey::ALGORITHM_DSA; - - /** - * The size of generated primary keys - * - * @var integer - * - * @see Crypt_GPG_KeyGenerator::setKeyParams() - */ - protected $keySize = 1024; - - /** - * The usages of generated primary keys - * - * This is a bitwise combination of the usage constants in - * {@link Crypt_GPG_SubKey}. - * - * @var integer - * - * @see Crypt_GPG_KeyGenerator::setKeyParams() - */ - protected $keyUsage = 6; // USAGE_SIGN | USAGE_CERTIFY - - /** - * The algorithm for generated sub-keys - * - * @var integer - * - * @see Crypt_GPG_KeyGenerator::setSubKeyParams() - */ - protected $subKeyAlgorithm = Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC; - - /** - * The size of generated sub-keys - * - * @var integer - * - * @see Crypt_GPG_KeyGenerator::setSubKeyParams() - */ - protected $subKeySize = 2048; - - /** - * The usages of generated sub-keys - * - * This is a bitwise combination of the usage constants in - * {@link Crypt_GPG_SubKey}. - * - * @var integer - * - * @see Crypt_GPG_KeyGenerator::setSubKeyParams() - */ - protected $subKeyUsage = Crypt_GPG_SubKey::USAGE_ENCRYPT; - - /** - * The GnuPG status handler to use for key generation - * - * @var Crypt_GPG_KeyGeneratorStatusHandler - * - * @see Crypt_GPG_KeyGenerator::setStatusHandler() - */ - protected $statusHandler = null; - - /** - * The GnuPG error handler to use for key generation - * - * @var Crypt_GPG_KeyGeneratorErrorHandler - * - * @see Crypt_GPG_KeyGenerator::setErrorHandler() - */ - protected $errorHandler = null; - - // }}} - // {{{ __construct() - - /** - * Creates a new GnuPG key generator - * - * Available options are: - * - * - string homedir - the directory where the GPG - * keyring files are stored. If not - * specified, Crypt_GPG uses the - * default of ~/.gnupg. - * - string publicKeyring - the file path of the public - * keyring. Use this if the public - * keyring is not in the homedir, or - * if the keyring is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * keyring with this option - * (/foo/bar/pubring.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string privateKeyring - the file path of the private - * keyring. Use this if the private - * keyring is not in the homedir, or - * if the keyring is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * keyring with this option - * (/foo/bar/secring.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string trustDb - the file path of the web-of-trust - * database. Use this if the trust - * database is not in the homedir, or - * if the database is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * trust database with this option - * (/foo/bar/trustdb.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string binary - the location of the GPG binary. If - * not specified, the driver attempts - * to auto-detect the GPG binary - * location using a list of known - * default locations for the current - * operating system. The option - * gpgBinary is a - * deprecated alias for this option. - * - string agent - the location of the GnuPG agent - * binary. The gpg-agent is only - * used for GnuPG 2.x. If not - * specified, the engine attempts - * to auto-detect the gpg-agent - * binary location using a list of - * know default locations for the - * current operating system. - * - boolean debug - whether or not to use debug mode. - * When debug mode is on, all - * communication to and from the GPG - * subprocess is logged. This can be - * - * @param array $options optional. An array of options used to create the - * GPG object. All options are optional and are - * represented as key-value pairs. - * - * @throws Crypt_GPG_FileException if the homedir does not exist - * and cannot be created. This can happen if homedir is - * not specified, Crypt_GPG is run as the web user, and the web - * user has no home directory. This exception is also thrown if any - * of the options publicKeyring, - * privateKeyring or trustDb options are - * specified but the files do not exist or are are not readable. - * This can happen if the user running the Crypt_GPG process (for - * example, the Apache user) does not have permission to read the - * files. - * - * @throws PEAR_Exception if the provided binary is invalid, or - * if no binary is provided and no suitable binary could - * be found. - * - * @throws PEAR_Exception if the provided agent is invalid, or - * if no agent is provided and no suitable gpg-agent - * cound be found. - */ - public function __construct(array $options = array()) - { - parent::__construct($options); - - $this->statusHandler = new Crypt_GPG_KeyGeneratorStatusHandler(); - $this->errorHandler = new Crypt_GPG_KeyGeneratorErrorHandler(); - } - - // }}} - // {{{ setExpirationDate() - - /** - * Sets the expiration date of generated keys - * - * @param string|integer $date either a string that may be parsed by - * PHP's strtotime() function, or an integer - * timestamp representing the number of seconds - * since the UNIX epoch. This date must be at - * least one date in the future. Keys that - * expire in the past may not be generated. Use - * an expiration date of 0 for keys that do not - * expire. - * - * @throws InvalidArgumentException if the date is not a valid format, or - * if the date is not at least one day in - * the future, or if the date is greater - * than 2038-01-19T03:14:07. - * - * @return Crypt_GPG_KeyGenerator the current object, for fluent interface. - */ - public function setExpirationDate($date) - { - if (is_int($date) || ctype_digit(strval($date))) { - $expirationDate = intval($date); - } else { - $expirationDate = strtotime($date); - } - - if ($expirationDate === false) { - throw new InvalidArgumentException( - sprintf( - 'Invalid expiration date format: "%s". Please use a ' . - 'format compatible with PHP\'s strtotime().', - $date - ) - ); - } - - if ($expirationDate !== 0 && $expirationDate < time() + 86400) { - throw new InvalidArgumentException( - 'Expiration date must be at least a day in the future.' - ); - } - - // GnuPG suffers from the 2038 bug - if ($expirationDate > 2147483647) { - throw new InvalidArgumentException( - 'Expiration date must not be greater than 2038-01-19T03:14:07.' - ); - } - - $this->expirationDate = $expirationDate; - - return $this; - } - - // }}} - // {{{ setPassphrase() - - /** - * Sets the passphrase of generated keys - * - * @param string $passphrase the passphrase to use for generated keys. Use - * null or an empty string for no passphrase. - * - * @return Crypt_GPG_KeyGenerator the current object, for fluent interface. - */ - public function setPassphrase($passphrase) - { - $this->passphrase = strval($passphrase); - return $this; - } - - // }}} - // {{{ setKeyParams() - - /** - * Sets the parameters for the primary key of generated key-pairs - * - * @param integer $algorithm the algorithm used by the key. This should be - * one of the Crypt_GPG_SubKey::ALGORITHM_* - * constants. - * @param integer $size optional. The size of the key. Different - * algorithms have different size requirements. - * If not specified, the default size for the - * specified algorithm will be used. If an - * invalid key size is used, GnuPG will do its - * best to round it to a valid size. - * @param integer $usage optional. A bitwise combination of key usages. - * If not specified, the primary key will be used - * only to sign and certify. This is the default - * behavior of GnuPG in interactive mode. Use - * the Crypt_GPG_SubKey::USAGE_* constants here. - * The primary key may be used to certify even - * if the certify usage is not specified. - * - * @return Crypt_GPG_KeyGenerator the current object, for fluent interface. - */ - public function setKeyParams($algorithm, $size = 0, $usage = 0) - { - $apgorithm = intval($algorithm); - - if ($algorithm === Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC) { - throw new Crypt_GPG_InvalidKeyParamsException( - 'Primary key algorithm must be capable of signing. The ' . - 'Elgamal algorithm can only encrypt.', - 0, - $algorithm, - $size, - $usage - ); - } - - if ($size != 0) { - $size = intval($size); - } - - if ($usage != 0) { - $usage = intval($usage); - } - - $usageEncrypt = Crypt_GPG_SubKey::USAGE_ENCRYPT; - - if ( $algorithm === Crypt_GPG_SubKey::ALGORITHM_DSA - && ($usage & $usageEncrypt) === $usageEncrypt - ) { - throw new Crypt_GPG_InvalidKeyParamsException( - 'The DSA algorithm is not capable of encrypting. Please ' . - 'specify a different algorithm or do not include encryption ' . - 'as a usage for the primary key.', - 0, - $algorithm, - $size, - $usage - ); - } - - $this->keyAlgorithm = $algorithm; - - if ($size != 0) { - $this->keySize = $size; - } - - if ($usage != 0) { - $this->keyUsage = $usage; - } - - return $this; - } - - // }}} - // {{{ setSubKeyParams() - - /** - * Sets the parameters for the sub-key of generated key-pairs - * - * @param integer $algorithm the algorithm used by the key. This should be - * one of the Crypt_GPG_SubKey::ALGORITHM_* - * constants. - * @param integer $size optional. The size of the key. Different - * algorithms have different size requirements. - * If not specified, the default size for the - * specified algorithm will be used. If an - * invalid key size is used, GnuPG will do its - * best to round it to a valid size. - * @param integer $usage optional. A bitwise combination of key usages. - * If not specified, the sub-key will be used - * only to encrypt. This is the default behavior - * of GnuPG in interactive mode. Use the - * Crypt_GPG_SubKey::USAGE_* constants here. - * - * @return Crypt_GPG_KeyGenerator the current object, for fluent interface. - */ - public function setSubKeyParams($algorithm, $size = '', $usage = 0) - { - $apgorithm = intval($algorithm); - - if ($size != 0) { - $size = intval($size); - } - - if ($usage != 0) { - $usage = intval($usage); - } - - $usageSign = Crypt_GPG_SubKey::USAGE_SIGN; - - if ( $algorithm === Crypt_GPG_SubKey::ALGORITHM_ELGAMAL_ENC - && ($usage & $usageSign) === $usageSign - ) { - throw new Crypt_GPG_InvalidKeyParamsException( - 'The Elgamal algorithm is not capable of signing. Please ' . - 'specify a different algorithm or do not include signing ' . - 'as a usage for the sub-key.', - 0, - $algorithm, - $size, - $usage - ); - } - - $usageEncrypt = Crypt_GPG_SubKey::USAGE_ENCRYPT; - - if ( $algorithm === Crypt_GPG_SubKey::ALGORITHM_DSA - && ($usage & $usageEncrypt) === $usageEncrypt - ) { - throw new Crypt_GPG_InvalidKeyParamsException( - 'The DSA algorithm is not capable of encrypting. Please ' . - 'specify a different algorithm or do not include encryption ' . - 'as a usage for the sub-key.', - 0, - $algorithm, - $size, - $usage - ); - } - - $this->subKeyAlgorithm = $algorithm; - - if ($size != 0) { - $this->subKeySize = $size; - } - - if ($usage != 0) { - $this->subKeyUsage = $usage; - } - - return $this; - } - - // }}} - // {{{ setStatusHandler() - - /** - * Sets the status handler to use for key generation - * - * Normally this method does not need to be used. It provides a means for - * dependency injection. - * - * @param Crypt_GPG_KeyStatusHandler $handler the key status handler to - * use. - * - * @return Crypt_GPG_KeyGenerator the current object, for fluent interface. - */ - public function setStatusHandler( - Crypt_GPG_KeyGeneratorStatusHandler $handler - ) { - $this->statusHandler = $handler; - return $this; - } - - // }}} - // {{{ setErrorHandler() - - /** - * Sets the error handler to use for key generation - * - * Normally this method does not need to be used. It provides a means for - * dependency injection. - * - * @param Crypt_GPG_KeyErrorHandler $handler the key error handler to - * use. - * - * @return Crypt_GPG_KeyGenerator the current object, for fluent interface. - */ - public function setErrorHandler( - Crypt_GPG_KeyGeneratorErrorHandler $handler - ) { - $this->errorHandler = $handler; - return $this; - } - - // }}} - // {{{ generateKey() - - /** - * Generates a new key-pair in the current keyring - * - * Secure key generation requires true random numbers, and as such can be - * solw. If the operating system runs out of entropy, key generation will - * block until more entropy is available. - * - * If quick key generation is important, a hardware entropy generator, or - * an entropy gathering daemon may be installed. For example, - * administrators of Debian systems may want to install the 'randomsound' - * package. - * - * @param string|Crypt_GPG_UserId $name either a {@link Crypt_GPG_UserId} - * object, or a string containing - * the name of the user id. - * @param string $email optional. If $name is - * specified as a string, this is - * the email address of the user id. - * @param string $comment optional. If $name is - * specified as a string, this is - * the comment of the user id. - * - * @return Crypt_GPG_Key the newly generated key. - * - * @throws Crypt_GPG_KeyNotCreatedException if the key parameters are - * incorrect, if an unknown error occurs during key generation, or - * if the newly generated key is not found in the keyring. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - */ - public function generateKey($name, $email = '', $comment = '') - { - $handle = uniqid('key', true); - - $userId = $this->getUserId($name, $email, $comment); - - $keyParams = array( - 'Key-Type' => $this->keyAlgorithm, - 'Key-Length' => $this->keySize, - 'Key-Usage' => $this->getUsage($this->keyUsage), - 'Subkey-Type' => $this->subKeyAlgorithm, - 'Subkey-Length' => $this->subKeySize, - 'Subkey-Usage' => $this->getUsage($this->subKeyUsage), - 'Name-Real' => $userId->getName(), - 'Handle' => $handle, - ); - - if ($this->expirationDate != 0) { - // GnuPG only accepts granularity of days - $expirationDate = date('Y-m-d', $this->expirationDate); - $keyParams['Expire-Date'] = $expirationDate; - } - - if ($this->passphrase != '') { - $keyParams['Passphrase'] = $this->passphrase; - } - - if ($userId->getEmail() != '') { - $keyParams['Name-Email'] = $userId->getEmail(); - } - - if ($userId->getComment() != '') { - $keyParams['Name-Comment'] = $userId->getComment(); - } - - - $keyParamsFormatted = array(); - foreach ($keyParams as $name => $value) { - $keyParamsFormatted[] = $name . ': ' . $value; - } - - $input = implode("\n", $keyParamsFormatted) . "\n%commit\n"; - - $statusHandler = clone $this->statusHandler; - $statusHandler->setHandle($handle); - - $errorHandler = clone $this->errorHandler; - - $this->engine->reset(); - $this->engine->addStatusHandler(array($statusHandler, 'handle')); - $this->engine->addErrorHandler(array($errorHandler, 'handle')); - $this->engine->setInput($input); - $this->engine->setOutput($output); - $this->engine->setOperation('--gen-key', array('--batch')); - $this->engine->run(); - - $code = $errorHandler->getErrorCode(); - switch ($code) { - case self::ERROR_BAD_KEY_PARAMS: - switch ($errorHandler->getLineNumber()) { - case 1: - throw new Crypt_GPG_InvalidKeyParamsException( - 'Invalid primary key algorithm specified.', - 0, - $this->keyAlgorithm, - $this->keySize, - $this->keyUsage - ); - case 4: - throw new Crypt_GPG_InvalidKeyParamsException( - 'Invalid sub-key algorithm specified.', - 0, - $this->subKeyAlgorithm, - $this->subKeySize, - $this->subKeyUsage - ); - default: - throw new Crypt_GPG_InvalidKeyParamsException( - 'Invalid key algorithm specified.' - ); - } - } - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - break; - default: - throw new Crypt_GPG_Exception( - 'Unknown error generating key-pair. Please use the \'debug\' ' . - 'option when creating the Crypt_GPG object, and file a bug ' . - 'report at ' . self::BUG_URI, - $code - ); - } - - $code = $statusHandler->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - break; - case self::ERROR_KEY_NOT_CREATED: - throw new Crypt_GPG_KeyNotCreatedException( - 'Unable to create new key-pair. Invalid key parameters. ' . - 'Make sure the specified key algorithms and sizes are ' . - 'correct.', - $code - ); - } - - $fingerprint = $statusHandler->getKeyFingerprint(); - $keys = $this->_getKeys($fingerprint); - - if (count($keys) === 0) { - throw new Crypt_GPG_KeyNotCreatedException( - sprintf( - 'Newly created key "%s" not found in keyring.', - $fingerprint - ) - ); - } - - return $keys[0]; - } - - // }}} - // {{{ getUsage() - - /** - * Builds a GnuPG key usage string suitable for key generation - * - * See doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG distribution} for detailed - * information on the key usage format. - * - * @param integer $usage a bitwise combination of the key usages. This is - * a combination of the Crypt_GPG_SubKey::USAGE_* - * constants. - * - * @return string the key usage string. - */ - protected function getUsage($usage) - { - $map = array( - Crypt_GPG_SubKey::USAGE_ENCRYPT => 'encrypt', - Crypt_GPG_SubKey::USAGE_SIGN => 'sign', - Crypt_GPG_SubKey::USAGE_CERTIFY => 'cert', - Crypt_GPG_SubKey::USAGE_AUTHENTICATION => 'auth', - ); - - // cert is always used for primary keys and does not need to be - // specified - $usage &= ~Crypt_GPG_SubKey::USAGE_CERTIFY; - - $usageArray = array(); - - foreach ($map as $key => $value) { - if (($usage & $key) === $key) { - $usageArray[] = $value; - } - } - - return implode(',', $usageArray); - } - - // }}} - // {{{ getUserId() - - /** - * Gets a user id object from parameters - * - * @param string|Crypt_GPG_UserId $name either a {@link Crypt_GPG_UserId} - * object, or a string containing - * the name of the user id. - * @param string $email optional. If $name is - * specified as a string, this is - * the email address of the user id. - * @param string $comment optional. If $name is - * specified as a string, this is - * the comment of the user id. - * - * @return Crypt_GPG_UserId a user id object for the specified parameters. - */ - protected function getUserId($name, $email = '', $comment = '') - { - if ($name instanceof Crypt_GPG_UserId) { - $userId = $name; - } else { - $userId = new Crypt_GPG_UserId(); - $userId->setName($name)->setEmail($email)->setComment($comment); - } - - return $userId; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/KeyGeneratorErrorHandler.php b/program/lib/Crypt/GPG/KeyGeneratorErrorHandler.php deleted file mode 100644 index ad9ebf395..000000000 --- a/program/lib/Crypt/GPG/KeyGeneratorErrorHandler.php +++ /dev/null @@ -1,121 +0,0 @@ - - * @copyright 2011-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id:$ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ - -/** - * Error line handler for the key generation operation - * - * This class is used internally by Crypt_GPG and does not need be used - * directly. See the {@link Crypt_GPG} class for end-user API. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2011-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -class Crypt_GPG_KeyGeneratorErrorHandler -{ - // {{{ protected properties - - /** - * Error code (if any) caused by key generation - * - * @var integer - */ - protected $errorCode = Crypt_GPG::ERROR_NONE; - - /** - * Line number at which the error occurred - * - * @var integer - */ - protected $lineNumber = null; - - // }}} - // {{{ handle() - - /** - * Handles an error line - * - * @param string $line the error line to handle. - * - * @return void - */ - public function handle($line) - { - $matches = array(); - $pattern = '/:([0-9]+): invalid algorithm$/'; - if (preg_match($pattern, $line, $matches) === 1) { - $this->errorCode = Crypt_GPG::ERROR_BAD_KEY_PARAMS; - $this->lineNumber = intval($matches[1]); - } - } - - // }}} - // {{{ getErrorCode() - - /** - * Gets the error code resulting from key gneration - * - * @return integer the error code resulting from key generation. - */ - public function getErrorCode() - { - return $this->errorCode; - } - - // }}} - // {{{ getLineNumber() - - /** - * Gets the line number at which the error occurred - * - * @return integer the line number at which the error occurred. Null if - * no error occurred. - */ - public function getLineNumber() - { - return $this->lineNumber; - } - - // }}} -} - -?> diff --git a/program/lib/Crypt/GPG/KeyGeneratorStatusHandler.php b/program/lib/Crypt/GPG/KeyGeneratorStatusHandler.php deleted file mode 100644 index 8b4c85c7a..000000000 --- a/program/lib/Crypt/GPG/KeyGeneratorStatusHandler.php +++ /dev/null @@ -1,173 +0,0 @@ - - * @copyright 2011-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id:$ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ - -/** - * Status line handler for the key generation operation - * - * This class is used internally by Crypt_GPG and does not need be used - * directly. See the {@link Crypt_GPG} class for end-user API. - * - * This class is responsible for parsing the final key fingerprint from the - * status output and for updating the key generation progress file. See - * doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG distribution} for detailed - * information on GPG's status output for the batch key generation operation. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2011-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -class Crypt_GPG_KeyGeneratorStatusHandler -{ - // {{{ protected properties - - /** - * The key fingerprint - * - * Ths key fingerprint is emitted by GPG after the key generation is - * complete. - * - * @var string - */ - protected $keyFingerprint = ''; - - /** - * The unique key handle used by this handler - * - * The key handle is used to track GPG status output for a particular key - * before the key has its own identifier. - * - * @var string - * - * @see Crypt_GPG_KeyGeneratorStatusHandler::setHandle() - */ - protected $handle = ''; - - /** - * Error code (if any) caused by key generation - * - * @var integer - */ - protected $errorCode = Crypt_GPG::ERROR_NONE; - - // }}} - // {{{ setHandle() - - /** - * Sets the unique key handle used by this handler - * - * The key handle is used to track GPG status output for a particular key - * before the key has its own identifier. - * - * @param string $handle the key handle this status handle will use. - * - * @return Crypt_GPG_KeyGeneratorStatusHandler the current object, for - * fluent interface. - */ - public function setHandle($handle) - { - $this->handle = strval($handle); - return $this; - } - - // }}} - // {{{ handle() - - /** - * Handles a status line - * - * @param string $line the status line to handle. - * - * @return void - */ - public function handle($line) - { - $tokens = explode(' ', $line); - switch ($tokens[0]) { - case 'KEY_CREATED': - if ($tokens[3] == $this->handle) { - $this->keyFingerprint = $tokens[2]; - } - break; - - case 'KEY_NOT_CREATED': - if ($tokens[1] == $this->handle) { - $this->errorCode = Crypt_GPG::ERROR_KEY_NOT_CREATED; - } - break; - - case 'PROGRESS': - // todo: at some point, support reporting status async - break; - } - } - - // }}} - // {{{ getKeyFingerprint() - - /** - * Gets the key fingerprint parsed by this handler - * - * @return array the key fingerprint parsed by this handler. - */ - public function getKeyFingerprint() - { - return $this->keyFingerprint; - } - - // }}} - // {{{ getErrorCode() - - /** - * Gets the error code resulting from key gneration - * - * @return integer the error code resulting from key generation. - */ - public function getErrorCode() - { - return $this->errorCode; - } - - // }}} -} - -?> diff --git a/program/lib/Crypt/GPG/PinEntry.php b/program/lib/Crypt/GPG/PinEntry.php deleted file mode 100644 index c09703617..000000000 --- a/program/lib/Crypt/GPG/PinEntry.php +++ /dev/null @@ -1,875 +0,0 @@ - - * @copyright 2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -/** - * CLI user-interface and parser. - */ -require_once 'Console/CommandLine.php'; - -// {{{ class Crypt_GPG_PinEntry - -/** - * A command-line dummy pinentry program for use with gpg-agent and Crypt_GPG - * - * This pinentry receives passphrases through en environment variable and - * automatically enters the PIN in response to gpg-agent requests. No user- - * interaction required. - * - * Thie pinentry can be run independently for testing and debugging with the - * following syntax: - * - *
- * Usage:
- *   crypt-gpg-pinentry [options]
- *
- * Options:
- *   -l log, --log=log  Optional location to log pinentry activity.
- *   -v, --verbose      Sets verbosity level. Use multiples for more detail
- *                      (e.g. "-vv").
- *   -h, --help         show this help message and exit
- *   --version          show the program version and exit
- * 
- * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @see Crypt_GPG::getKeys() - */ -class Crypt_GPG_PinEntry -{ - // {{{ class constants - - /** - * Verbosity level for showing no output. - */ - const VERBOSITY_NONE = 0; - - /** - * Verbosity level for showing error output. - */ - const VERBOSITY_ERRORS = 1; - - /** - * Verbosity level for showing all output, including Assuan protocol - * messages. - */ - const VERBOSITY_ALL = 2; - - /** - * Length of buffer for reading lines from the Assuan server. - * - * PHP reads 8192 bytes. If this is set to less than 8192, PHP reads 8192 - * and buffers the rest so we might as well just read 8192. - * - * Using values other than 8192 also triggers PHP bugs. - * - * @see http://bugs.php.net/bug.php?id=35224 - */ - const CHUNK_SIZE = 8192; - - // }}} - // {{{ protected properties - - /** - * File handle for the input stream - * - * @var resource - */ - protected $stdin = null; - - /** - * File handle for the output stream - * - * @var resource - */ - protected $stdout = null; - - /** - * File handle for the log file if a log file is used - * - * @var resource - */ - protected $logFile = null; - - /** - * Whether or not this pinentry is finished and is exiting - * - * @var boolean - */ - protected $moribund = false; - - /** - * Verbosity level - * - * One of: - * - {@link Crypt_GPG_PinEntry::VERBOSITY_NONE}, - * - {@link Crypt_GPG_PinEntry::VERBOSITY_ERRORS}, or - * - {@link Crypt_GPG_PinEntry::VERBOSITY_ALL} - * - * @var integer - */ - protected $verbosity = self::VERBOSITY_NONE; - - /** - * The command-line interface parser for this pinentry - * - * @var Console_CommandLine - * - * @see Crypt_GPG_PinEntry::getParser() - */ - protected $parser = null; - - /** - * PINs to be entered by this pinentry - * - * An indexed array of associative arrays in the form: - * - * $keyId, - * 'passphrase' => $passphrase - * ), - * ... - * ); - * ?> - * - * - * This array is parsed from the environment variable - * PINENTRY_USER_DATA. - * - * @var array - * - * @see Crypt_GPG_PinEntry::initPinsFromENV() - */ - protected $pins = array(); - - /** - * PINs that have been tried for the current PIN - * - * This is an associative array indexed by the key identifier with - * values being the same as elements in the {@link Crypt_GPG_PinEntry::$pins} - * array. - * - * @var array - */ - protected $triedPins = array(); - - /** - * The PIN currently being requested by the Assuan server - * - * If set, this is an associative array in the form: - * - * $shortKeyId, - * 'userId' => $userIdString - * ); - * ?> - * - * - * @var array|null - */ - protected $currentPin = null; - - // }}} - // {{{ __invoke() - - /** - * Runs this pinentry - * - * @return void - */ - public function __invoke() - { - $this->parser = $this->getCommandLineParser(); - - try { - $result = $this->parser->parse(); - - $this->setVerbosity($result->options['verbose']); - $this->setLogFilename($result->options['log']); - - $this->connect(); - $this->initPinsFromENV(); - - while (($line = fgets($this->stdin, self::CHUNK_SIZE)) !== false) { - $this->parseCommand(mb_substr($line, 0, -1, '8bit')); - if ($this->moribund) { - break; - } - } - - $this->disconnect(); - - } catch (Console_CommandLineException $e) { - $this->log($e->getMessage() . PHP_EOL, slf::VERBOSITY_ERRORS); - exit(1); - } catch (Exception $e) { - $this->log($e->getMessage() . PHP_EOL, self::VERBOSITY_ERRORS); - $this->log($e->getTraceAsString() . PHP_EOL, self::VERBOSITY_ERRORS); - exit(1); - } - } - - // }}} - // {{{ setVerbosity() - - /** - * Sets the verbosity of logging for this pinentry - * - * Verbosity levels are: - * - * - {@link Crypt_GPG_PinEntry::VERBOSITY_NONE} - no logging. - * - {@link Crypt_GPG_PinEntry::VERBOSITY_ERRORS} - log errors only. - * - {@link Crypt_GPG_PinEntry::VERBOSITY_ALL} - log everything, including - * the assuan protocol. - * - * @param integer $verbosity the level of verbosity of this pinentry. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - public function setVerbosity($verbosity) - { - $this->verbosity = (integer)$verbosity; - return $this; - } - - // }}} - // {{{ setLogFilename() - - /** - * Sets the log file location - * - * @param string $filename the new log filename to use. If an empty string - * is used, file-based logging is disabled. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - public function setLogFilename($filename) - { - if (is_resource($this->logFile)) { - fflush($this->logFile); - fclose($this->logFile); - $this->logFile = null; - } - - if ($filename != '') { - if (($this->logFile = fopen($filename, 'w')) === false) { - $this->log( - 'Unable to open log file "' . $filename . '" ' - . 'for writing.' . PHP_EOL, - self::VERBOSITY_ERRORS - ); - exit(1); - } else { - stream_set_write_buffer($this->logFile, 0); - } - } - - return $this; - } - - // }}} - // {{{ getUIXML() - - /** - * Gets the CLI user-interface definition for this pinentry - * - * Detects whether or not this package is PEAR-installed and appropriately - * locates the XML UI definition. - * - * @return string the location of the CLI user-interface definition XML. - */ - protected function getUIXML() - { - $dir = '@data-dir@' . DIRECTORY_SEPARATOR - . '@package-name@' . DIRECTORY_SEPARATOR . 'data'; - - // Check if we're running directly from a git checkout or if we're - // running from a PEAR-packaged version. - if ($dir[0] == '@') { - $dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' - . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data'; - } - - return $dir . DIRECTORY_SEPARATOR . 'pinentry-cli.xml'; - } - - // }}} - // {{{ getCommandLineParser() - - /** - * Gets the CLI parser for this pinentry - * - * @return Console_CommandLine the CLI parser for this pinentry. - */ - protected function getCommandLineParser() - { - return Console_CommandLine::fromXmlFile($this->getUIXML()); - } - - // }}} - // {{{ log() - - /** - * Logs a message at the specified verbosity level - * - * If a log file is used, the message is written to the log. Otherwise, - * the message is sent to STDERR. - * - * @param string $data the message to log. - * @param integer $level the verbosity level above which the message should - * be logged. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function log($data, $level) - { - if ($this->verbosity >= $level) { - if (is_resource($this->logFile)) { - fwrite($this->logFile, $data); - fflush($this->logFile); - } else { - $this->parser->outputter->stderr($data); - } - } - - return $this; - } - - // }}} - // {{{ connect() - - /** - * Connects this pinentry to the assuan server - * - * Opens I/O streams and sends initial handshake. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function connect() - { - // Binary operations will not work on Windows with PHP < 5.2.6. - $rb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'r' : 'rb'; - $wb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'w' : 'wb'; - - $this->stdin = fopen('php://stdin', $rb); - $this->stdout = fopen('php://stdout', $wb); - - if (function_exists('stream_set_read_buffer')) { - stream_set_read_buffer($this->stdin, 0); - } - stream_set_write_buffer($this->stdout, 0); - - // initial handshake - $this->send($this->getOK('Crypt_GPG pinentry ready and waiting')); - - return $this; - } - - // }}} - // {{{ parseCommand() - - /** - * Parses an assuan command and performs the appropriate action - * - * Documentation of the assuan commands for pinentry is limited to - * non-existent. Most of these commands were taken from the C source code - * to gpg-agent and pinentry. - * - * Additional context was provided by using strace -f when calling the - * gpg-agent. - * - * @param string $line the assuan command line to parse - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function parseCommand($line) - { - $this->log('<- ' . $line . PHP_EOL, self::VERBOSITY_ALL); - - $parts = explode(' ', $line, 2); - - $command = $parts[0]; - - if (count($parts) === 2) { - $data = $parts[1]; - } else { - $data = null; - } - - switch ($command) { - case 'SETDESC': - return $this->sendSetDescription($data); - - case 'SETPROMPT': - case 'SETERROR': - case 'SETOK': - case 'SETNOTOK': - case 'SETCANCEL': - case 'SETQUALITYBAR': - case 'SETQUALITYBAR_TT': - case 'OPTION': - return $this->sendNotImplementedOK(); - - case 'MESSAGE': - return $this->sendMessage(); - - case 'CONFIRM': - return $this->sendConfirm(); - - case 'GETINFO': - return $this->sendGetInfo($data); - - case 'GETPIN': - return $this->sendGetPin($data); - - case 'RESET': - return $this->sendReset(); - - case 'BYE': - return $this->sendBye(); - } - } - - // }}} - // {{{ initPinsFromENV() - - /** - * Initializes the PINs to be entered by this pinentry from the environment - * variable PINENTRY_USER_DATA - * - * The PINs are parsed from a JSON-encoded string. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function initPinsFromENV() - { - if (($userData = getenv('PINENTRY_USER_DATA')) !== false) { - $pins = json_decode($userData, true); - if ($pins === null) { - $this->log( - '-- failed to parse user data' . PHP_EOL, - self::VERBOSITY_ERRORS - ); - } else { - $this->pins = $pins; - $this->log( - '-- got user data [not showing passphrases]' . PHP_EOL, - self::VERBOSITY_ALL - ); - } - } - - return $this; - } - - // }}} - // {{{ disconnect() - - /** - * Disconnects this pinentry from the Assuan server - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function disconnect() - { - $this->log('-- disconnecting' . PHP_EOL, self::VERBOSITY_ALL); - - fflush($this->stdout); - fclose($this->stdout); - fclose($this->stdin); - - $this->stdin = null; - $this->stdout = null; - - $this->log('-- disconnected' . PHP_EOL, self::VERBOSITY_ALL); - - if (is_resource($this->logFile)) { - fflush($this->logFile); - fclose($this->logFile); - $this->logFile = null; - } - - return $this; - } - - // }}} - // {{{ sendNotImplementedOK() - - /** - * Sends an OK response for a not implemented feature - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendNotImplementedOK() - { - return $this->send($this->getOK()); - } - - // }}} - // {{{ sendSetDescription() - - /** - * Parses the currently requested key identifier and user identifier from - * the description passed to this pinentry - * - * @param string $text the raw description sent from gpg-agent. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendSetDescription($text) - { - $text = rawurldecode($text); - $matches = array(); - // TODO: handle user id with quotation marks - $exp = '/\n"(.+)"\n.*\sID ([A-Z0-9]+),\n/mu'; - if (preg_match($exp, $text, $matches) === 1) { - $userId = $matches[1]; - $keyId = $matches[2]; - - // only reset tried pins for new requested pin - if ( $this->currentPin === null - || $this->currentPin['keyId'] !== $keyId - ) { - $this->currentPin = array( - 'userId' => $userId, - 'keyId' => $keyId - ); - $this->triedPins = array(); - $this->log( - '-- looking for PIN for ' . $keyId . PHP_EOL, - self::VERBOSITY_ALL - ); - } - } - - return $this->send($this->getOK()); - } - - // }}} - // {{{ sendConfirm() - - /** - * Tells the assuan server the PIN entry was confirmed (not cancelled) - * by pressing the fake 'close' button - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendConfirm() - { - return $this->sendButtonInfo('close'); - } - - // }}} - // {{{ sendMessage() - - /** - * Tells the assuan server that any requested pop-up messages were confirmed - * by pressing the fake 'close' button - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendMessage() - { - return $this->sendButtonInfo('close'); - } - - // }}} - // {{{ sendButtonInfo() - - /** - * Sends information about pressed buttons to the assuan server - * - * This is used to fake a user-interface for this pinentry. - * - * @param string $text the button status to send. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendButtonInfo($text) - { - return $this->send('BUTTON_INFO ' . $text . "\n"); - } - - // }}} - // {{{ sendGetPin() - - /** - * Sends the PIN value for the currently requested key - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendGetPin() - { - $foundPin = ''; - - if (is_array($this->currentPin)) { - $keyIdLength = mb_strlen($this->currentPin['keyId'], '8bit'); - - // search for the pin - foreach ($this->pins as $pin) { - // only check pins we haven't tried - if (!isset($this->triedPins[$pin['keyId']])) { - - // get last X characters of key identifier to compare - $keyId = mb_substr( - $pin['keyId'], - -$keyIdLength, - mb_strlen($pin['keyId'], '8bit'), - '8bit' - ); - - if ($keyId === $this->currentPin['keyId']) { - $foundPin = $pin['passphrase']; - $this->triedPins[$pin['keyId']] = $pin; - break; - } - } - } - } - - return $this - ->send($this->getData($foundPin)) - ->send($this->getOK()); - } - - // }}} - // {{{ sendGetInfo() - - /** - * Sends information about this pinentry - * - * @param string $data the information requested by the assuan server. - * Currently only 'pid' is supported. Other requests - * return no information. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendGetInfo($data) - { - $parts = explode(' ', $data, 2); - $command = reset($parts); - - switch ($command) { - case 'pid': - return $this->sendGetInfoPID(); - default: - return $this->send($this->getOK()); - } - - return $this; - } - // }}} - // {{{ sendGetInfoPID() - - /** - * Sends the PID of this pinentry to the assuan server - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendGetInfoPID() - { - return $this - ->send($this->getData(getmypid())) - ->send($this->getOK()); - } - - // }}} - // {{{ sendBye() - - /** - * Flags this pinentry for disconnection and sends an OK response - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendBye() - { - $return = $this->send($this->getOK('closing connection')); - $this->moribund = true; - return $return; - } - - // }}} - // {{{ sendReset() - - /** - * Resets this pinentry and sends an OK response - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function sendReset() - { - $this->currentPin = null; - $this->triedPins = array(); - return $this->send($this->getOK()); - } - - // }}} - // {{{ getOK() - - /** - * Gets an OK response to send to the assuan server - * - * @param string $data an optional message to include with the OK response. - * - * @return string the OK response. - */ - protected function getOK($data = null) - { - $return = 'OK'; - - if ($data) { - $return .= ' ' . $data; - } - - return $return . "\n"; - } - - // }}} - // {{{ getData() - - /** - * Gets data ready to send to the assuan server - * - * Data is appropriately escaped and long lines are wrapped. - * - * @param string $data the data to send to the assuan server. - * - * @return string the properly escaped, formatted data. - * - * @see http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html - */ - protected function getData($data) - { - // Escape data. Only %, \n and \r need to be escaped but other - // values are allowed to be escaped. See - // http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html - $data = rawurlencode($data); - $data = $this->getWordWrappedData($data, 'D'); - return $data; - } - - // }}} - // {{{ getComment() - - /** - * Gets a comment ready to send to the assuan server - * - * @param string $data the comment to send to the assuan server. - * - * @return string the properly formatted comment. - * - * @see http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html - */ - protected function getComment($data) - { - return $this->getWordWrappedData($data, '#'); - } - - // }}} - // {{{ getWordWrappedData() - - /** - * Wraps strings at 1,000 bytes without splitting UTF-8 multibyte - * characters - * - * Each line is prepended with the specified line prefix. Wrapped lines - * are automatically appended with \ characters. - * - * Protocol strings are UTF-8 but maximum line length is 1,000 bytes. - * mb_strcut() is used so we can limit line length by bytes - * and not split characters across multiple lines. - * - * @param string $data the data to wrap. - * @param string $prefix a single character to use as the line prefix. For - * example, 'D' or '#'. - * - * @return string the word-wrapped, prefixed string. - * - * @see http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html - */ - protected function getWordWrappedData($data, $prefix) - { - $lines = array(); - - do { - if (mb_strlen($data, '8bit') > 997) { - $line = $prefix . ' ' . mb_strcut($data, 0, 996, 'utf-8') . "\\\n"; - $lines[] = $line; - $lineLength = mb_strlen($line, '8bit') - 1; - $dataLength = mb_substr($data, '8bit'); - $data = mb_substr( - $data, - $lineLength, - $dataLength - $lineLength, - '8bit' - ); - } else { - $lines[] = $prefix . ' ' . $data . "\n"; - $data = ''; - } - } while ($data != ''); - - return implode('', $lines); - } - - // }}} - // {{{ send() - - /** - * Sends raw data to the assuan server - * - * @param string $data the data to send. - * - * @return Crypt_GPG_PinEntry the current object, for fluent interface. - */ - protected function send($data) - { - $this->log('-> ' . $data, self::VERBOSITY_ALL); - fwrite($this->stdout, $data); - fflush($this->stdout); - return $this; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/ProcessControl.php b/program/lib/Crypt/GPG/ProcessControl.php deleted file mode 100644 index d6dae0325..000000000 --- a/program/lib/Crypt/GPG/ProcessControl.php +++ /dev/null @@ -1,150 +0,0 @@ - - * @copyright 2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -// {{{ class Crypt_GPG_ProcessControl - -/** - * A class for monitoring and terminating processes by PID - * - * This is used to safely terminate the gpg-agent for GnuPG 2.x. This class - * is limited in its abilities and can only check if a PID is running and - * send a PID SIGTERM. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - */ -class Crypt_GPG_ProcessControl -{ - // {{{ protected properties - - /** - * The PID (process identifier) being monitored - * - * @var integer - */ - protected $pid; - - // }}} - // {{{ __construct() - - /** - * Creates a new process controller from the given PID (process identifier) - * - * @param integer $pid the PID (process identifier). - */ - public function __construct($pid) - { - $this->pid = $pid; - } - - // }}} - // {{{ public function getPid() - - /** - * Gets the PID (process identifier) being controlled - * - * @return integer the PID being controlled. - */ - public function getPid() - { - return $this->pid; - } - - // }}} - // {{{ isRunning() - - /** - * Checks if the process is running - * - * Uses ps on UNIX-like systems and tasklist on - * Windows. - * - * @return boolean true if the process is running, false if not. - */ - public function isRunning() - { - $running = false; - - if (PHP_OS === 'WINNT') { - $command = 'tasklist /fo csv /nh /fi ' - . escapeshellarg('PID eq ' . $this->pid); - - $result = exec($command); - $parts = explode(',', $result); - $running = (count($parts) > 1 && trim($parts[1], '"') == $this->pid); - } else { - $result = exec('ps -p ' . escapeshellarg($this->pid) . ' -o pid='); - $running = (trim($result) == $this->pid); - } - - return $running; - } - - // }}} - // {{{ terminate() - - /** - * Ends the process gracefully - * - * The signal SIGTERM is sent to the process. The gpg-agent process will - * end gracefully upon receiving the SIGTERM signal. Upon 3 consecutive - * SIGTERM signals the gpg-agent will forcefully shut down. - * - * If the posix extension is available, posix_kill() - * is used. Otherwise kill is used on UNIX-like systems and - * taskkill is used in Windows. - * - * @return void - */ - public function terminate() - { - if (function_exists('posix_kill')) { - posix_kill($this->pid, 15); - } elseif (PHP_OS === 'WINNT') { - exec('taskkill /PID ' . escapeshellarg($this->pid)); - } else { - exec('kill -15 ' . escapeshellarg($this->pid)); - } - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/Signature.php b/program/lib/Crypt/GPG/Signature.php deleted file mode 100644 index 1d28a1188..000000000 --- a/program/lib/Crypt/GPG/Signature.php +++ /dev/null @@ -1,427 +0,0 @@ - - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -/** - * User id class definition - */ -require_once 'Crypt/GPG/UserId.php'; - -// {{{ class Crypt_GPG_Signature - -/** - * A class for GPG signature information - * - * This class is used to store the results of the Crypt_GPG::verify() method. - * - * @category Encryption - * @package Crypt_GPG - * @author Nathan Fredrickson - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @see Crypt_GPG::verify() - */ -class Crypt_GPG_Signature -{ - // {{{ class properties - - /** - * A base64-encoded string containing a unique id for this signature if - * this signature has been verified as ok - * - * This id is used to prevent replay attacks and is not present for all - * types of signatures. - * - * @var string - */ - private $_id = ''; - - /** - * The fingerprint of the key used to create the signature - * - * @var string - */ - private $_keyFingerprint = ''; - - /** - * The id of the key used to create the signature - * - * @var string - */ - private $_keyId = ''; - - /** - * The creation date of this signature - * - * This is a Unix timestamp. - * - * @var integer - */ - private $_creationDate = 0; - - /** - * The expiration date of the signature - * - * This is a Unix timestamp. If this signature does not expire, this will - * be zero. - * - * @var integer - */ - private $_expirationDate = 0; - - /** - * The user id associated with this signature - * - * @var Crypt_GPG_UserId - */ - private $_userId = null; - - /** - * Whether or not this signature is valid - * - * @var boolean - */ - private $_isValid = false; - - // }}} - // {{{ __construct() - - /** - * Creates a new signature - * - * Signatures can be initialized from an array of named values. Available - * names are: - * - * - string id - the unique id of this signature. - * - string fingerprint - the fingerprint of the key used to - * create the signature. The fingerprint - * should not contain formatting - * characters. - * - string keyId - the id of the key used to create the - * the signature. - * - integer creation - the date the signature was created. - * This is a UNIX timestamp. - * - integer expiration - the date the signature expired. This - * is a UNIX timestamp. If the signature - * does not expire, use 0. - * - boolean valid - whether or not the signature is valid. - * - string userId - the user id associated with the - * signature. This may also be a - * {@link Crypt_GPG_UserId} object. - * - * @param Crypt_GPG_Signature|array $signature optional. Either an existing - * signature object, which is copied; or an array of initial values. - */ - public function __construct($signature = null) - { - // copy from object - if ($signature instanceof Crypt_GPG_Signature) { - $this->_id = $signature->_id; - $this->_keyFingerprint = $signature->_keyFingerprint; - $this->_keyId = $signature->_keyId; - $this->_creationDate = $signature->_creationDate; - $this->_expirationDate = $signature->_expirationDate; - $this->_isValid = $signature->_isValid; - - if ($signature->_userId instanceof Crypt_GPG_UserId) { - $this->_userId = clone $signature->_userId; - } - } - - // initialize from array - if (is_array($signature)) { - if (array_key_exists('id', $signature)) { - $this->setId($signature['id']); - } - - if (array_key_exists('fingerprint', $signature)) { - $this->setKeyFingerprint($signature['fingerprint']); - } - - if (array_key_exists('keyId', $signature)) { - $this->setKeyId($signature['keyId']); - } - - if (array_key_exists('creation', $signature)) { - $this->setCreationDate($signature['creation']); - } - - if (array_key_exists('expiration', $signature)) { - $this->setExpirationDate($signature['expiration']); - } - - if (array_key_exists('valid', $signature)) { - $this->setValid($signature['valid']); - } - - if (array_key_exists('userId', $signature)) { - $userId = new Crypt_GPG_UserId($signature['userId']); - $this->setUserId($userId); - } - } - } - - // }}} - // {{{ getId() - - /** - * Gets the id of this signature - * - * @return string a base64-encoded string containing a unique id for this - * signature. This id is used to prevent replay attacks and - * is not present for all types of signatures. - */ - public function getId() - { - return $this->_id; - } - - // }}} - // {{{ getKeyFingerprint() - - /** - * Gets the fingerprint of the key used to create this signature - * - * @return string the fingerprint of the key used to create this signature. - */ - public function getKeyFingerprint() - { - return $this->_keyFingerprint; - } - - // }}} - // {{{ getKeyId() - - /** - * Gets the id of the key used to create this signature - * - * Whereas the fingerprint of the signing key may not always be available - * (for example if the signature is bad), the id should always be - * available. - * - * @return string the id of the key used to create this signature. - */ - public function getKeyId() - { - return $this->_keyId; - } - - // }}} - // {{{ getCreationDate() - - /** - * Gets the creation date of this signature - * - * @return integer the creation date of this signature. This is a Unix - * timestamp. - */ - public function getCreationDate() - { - return $this->_creationDate; - } - - // }}} - // {{{ getExpirationDate() - - /** - * Gets the expiration date of the signature - * - * @return integer the expiration date of this signature. This is a Unix - * timestamp. If this signature does not expire, this will - * be zero. - */ - public function getExpirationDate() - { - return $this->_expirationDate; - } - - // }}} - // {{{ getUserId() - - /** - * Gets the user id associated with this signature - * - * @return Crypt_GPG_UserId the user id associated with this signature. - */ - public function getUserId() - { - return $this->_userId; - } - - // }}} - // {{{ isValid() - - /** - * Gets whether or no this signature is valid - * - * @return boolean true if this signature is valid and false if it is not. - */ - public function isValid() - { - return $this->_isValid; - } - - // }}} - // {{{ setId() - - /** - * Sets the id of this signature - * - * @param string $id a base64-encoded string containing a unique id for - * this signature. - * - * @return Crypt_GPG_Signature the current object, for fluent interface. - * - * @see Crypt_GPG_Signature::getId() - */ - public function setId($id) - { - $this->_id = strval($id); - return $this; - } - - // }}} - // {{{ setKeyFingerprint() - - /** - * Sets the key fingerprint of this signature - * - * @param string $fingerprint the key fingerprint of this signature. This - * is the fingerprint of the primary key used to - * create this signature. - * - * @return Crypt_GPG_Signature the current object, for fluent interface. - */ - public function setKeyFingerprint($fingerprint) - { - $this->_keyFingerprint = strval($fingerprint); - return $this; - } - - // }}} - // {{{ setKeyId() - - /** - * Sets the key id of this signature - * - * @param string $id the key id of this signature. This is the id of the - * primary key used to create this signature. - * - * @return Crypt_GPG_Signature the current object, for fluent interface. - */ - public function setKeyId($id) - { - $this->_keyId = strval($id); - return $this; - } - - // }}} - // {{{ setCreationDate() - - /** - * Sets the creation date of this signature - * - * @param integer $creationDate the creation date of this signature. This - * is a Unix timestamp. - * - * @return Crypt_GPG_Signature the current object, for fluent interface. - */ - public function setCreationDate($creationDate) - { - $this->_creationDate = intval($creationDate); - return $this; - } - - // }}} - // {{{ setExpirationDate() - - /** - * Sets the expiration date of this signature - * - * @param integer $expirationDate the expiration date of this signature. - * This is a Unix timestamp. Specify zero if - * this signature does not expire. - * - * @return Crypt_GPG_Signature the current object, for fluent interface. - */ - public function setExpirationDate($expirationDate) - { - $this->_expirationDate = intval($expirationDate); - return $this; - } - - // }}} - // {{{ setUserId() - - /** - * Sets the user id associated with this signature - * - * @param Crypt_GPG_UserId $userId the user id associated with this - * signature. - * - * @return Crypt_GPG_Signature the current object, for fluent interface. - */ - public function setUserId(Crypt_GPG_UserId $userId) - { - $this->_userId = $userId; - return $this; - } - - // }}} - // {{{ setValid() - - /** - * Sets whether or not this signature is valid - * - * @param boolean $isValid true if this signature is valid and false if it - * is not. - * - * @return Crypt_GPG_Signature the current object, for fluent interface. - */ - public function setValid($isValid) - { - $this->_isValid = ($isValid) ? true : false; - return $this; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/SubKey.php b/program/lib/Crypt/GPG/SubKey.php deleted file mode 100644 index 59245cac1..000000000 --- a/program/lib/Crypt/GPG/SubKey.php +++ /dev/null @@ -1,672 +0,0 @@ - - * @author Nathan Fredrickson - * @copyright 2005-2010 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -// {{{ class Crypt_GPG_SubKey - -/** - * A class for GPG sub-key information - * - * This class is used to store the results of the {@link Crypt_GPG::getKeys()} - * method. Sub-key objects are members of a {@link Crypt_GPG_Key} object. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @author Nathan Fredrickson - * @copyright 2005-2010 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @see Crypt_GPG::getKeys() - * @see Crypt_GPG_Key::getSubKeys() - */ -class Crypt_GPG_SubKey -{ - // {{{ algorithm class constants - - /** - * RSA encryption algorithm. - */ - const ALGORITHM_RSA = 1; - - /** - * Elgamal encryption algorithm (encryption only). - */ - const ALGORITHM_ELGAMAL_ENC = 16; - - /** - * DSA encryption algorithm (sometimes called DH, sign only). - */ - const ALGORITHM_DSA = 17; - - /** - * Elgamal encryption algorithm (signage and encryption - should not be - * used). - */ - const ALGORITHM_ELGAMAL_ENC_SGN = 20; - - // }}} - // {{{ usage class constants - - /** - * Key can be used to encrypt - */ - const USAGE_ENCRYPT = 1; - - /** - * Key can be used to sign - */ - const USAGE_SIGN = 2; - - /** - * Key can be used to certify other keys - */ - const USAGE_CERTIFY = 4; - - /** - * Key can be used for authentication - */ - const USAGE_AUTHENTICATION = 8; - - // }}} - // {{{ class properties - - /** - * The id of this sub-key - * - * @var string - */ - private $_id = ''; - - /** - * The algorithm used to create this sub-key - * - * The value is one of the Crypt_GPG_SubKey::ALGORITHM_* constants. - * - * @var integer - */ - private $_algorithm = 0; - - /** - * The fingerprint of this sub-key - * - * @var string - */ - private $_fingerprint = ''; - - /** - * Length of this sub-key in bits - * - * @var integer - */ - private $_length = 0; - - /** - * Date this sub-key was created - * - * This is a Unix timestamp. - * - * @var integer - */ - private $_creationDate = 0; - - /** - * Date this sub-key expires - * - * This is a Unix timestamp. If this sub-key does not expire, this will be - * zero. - * - * @var integer - */ - private $_expirationDate = 0; - - /** - * Whether or not this sub-key can sign data - * - * @var boolean - */ - private $_canSign = false; - - /** - * Whether or not this sub-key can encrypt data - * - * @var boolean - */ - private $_canEncrypt = false; - - /** - * Whether or not the private key for this sub-key exists in the keyring - * - * @var boolean - */ - private $_hasPrivate = false; - - /** - * Whether or not this sub-key is revoked - * - * @var boolean - */ - private $_isRevoked = false; - - // }}} - // {{{ __construct() - - /** - * Creates a new sub-key object - * - * Sub-keys can be initialized from an array of named values. Available - * names are: - * - * - string id - the key id of the sub-key. - * - integer algorithm - the encryption algorithm of the - * sub-key. - * - string fingerprint - the fingerprint of the sub-key. The - * fingerprint should not contain - * formatting characters. - * - integer length - the length of the sub-key in bits. - * - integer creation - the date the sub-key was created. - * This is a UNIX timestamp. - * - integer expiration - the date the sub-key expires. This - * is a UNIX timestamp. If the sub-key - * does not expire, use 0. - * - boolean canSign - whether or not the sub-key can be - * used to sign data. - * - boolean canEncrypt - whether or not the sub-key can be - * used to encrypt data. - * - boolean hasPrivate - whether or not the private key for - * the sub-key exists in the keyring. - * - boolean isRevoked - whether or not this sub-key is - * revoked. - * - * @param Crypt_GPG_SubKey|string|array $key optional. Either an existing - * sub-key object, which is copied; a sub-key string, which is - * parsed; or an array of initial values. - */ - public function __construct($key = null) - { - // parse from string - if (is_string($key)) { - $key = self::parse($key); - } - - // copy from object - if ($key instanceof Crypt_GPG_SubKey) { - $this->_id = $key->_id; - $this->_algorithm = $key->_algorithm; - $this->_fingerprint = $key->_fingerprint; - $this->_length = $key->_length; - $this->_creationDate = $key->_creationDate; - $this->_expirationDate = $key->_expirationDate; - $this->_canSign = $key->_canSign; - $this->_canEncrypt = $key->_canEncrypt; - $this->_hasPrivate = $key->_hasPrivate; - $this->_isRevoked = $key->_isRevoked; - } - - // initialize from array - if (is_array($key)) { - if (array_key_exists('id', $key)) { - $this->setId($key['id']); - } - - if (array_key_exists('algorithm', $key)) { - $this->setAlgorithm($key['algorithm']); - } - - if (array_key_exists('fingerprint', $key)) { - $this->setFingerprint($key['fingerprint']); - } - - if (array_key_exists('length', $key)) { - $this->setLength($key['length']); - } - - if (array_key_exists('creation', $key)) { - $this->setCreationDate($key['creation']); - } - - if (array_key_exists('expiration', $key)) { - $this->setExpirationDate($key['expiration']); - } - - if (array_key_exists('canSign', $key)) { - $this->setCanSign($key['canSign']); - } - - if (array_key_exists('canEncrypt', $key)) { - $this->setCanEncrypt($key['canEncrypt']); - } - - if (array_key_exists('hasPrivate', $key)) { - $this->setHasPrivate($key['hasPrivate']); - } - - if (array_key_exists('isRevoked', $key)) { - $this->setRevoked($key['isRevoked']); - } - } - } - - // }}} - // {{{ getId() - - /** - * Gets the id of this sub-key - * - * @return string the id of this sub-key. - */ - public function getId() - { - return $this->_id; - } - - // }}} - // {{{ getAlgorithm() - - /** - * Gets the algorithm used by this sub-key - * - * The algorithm should be one of the Crypt_GPG_SubKey::ALGORITHM_* - * constants. - * - * @return integer the algorithm used by this sub-key. - */ - public function getAlgorithm() - { - return $this->_algorithm; - } - - // }}} - // {{{ getCreationDate() - - /** - * Gets the creation date of this sub-key - * - * This is a Unix timestamp. - * - * @return integer the creation date of this sub-key. - */ - public function getCreationDate() - { - return $this->_creationDate; - } - - // }}} - // {{{ getExpirationDate() - - /** - * Gets the date this sub-key expires - * - * This is a Unix timestamp. If this sub-key does not expire, this will be - * zero. - * - * @return integer the date this sub-key expires. - */ - public function getExpirationDate() - { - return $this->_expirationDate; - } - - // }}} - // {{{ getFingerprint() - - /** - * Gets the fingerprint of this sub-key - * - * @return string the fingerprint of this sub-key. - */ - public function getFingerprint() - { - return $this->_fingerprint; - } - - // }}} - // {{{ getLength() - - /** - * Gets the length of this sub-key in bits - * - * @return integer the length of this sub-key in bits. - */ - public function getLength() - { - return $this->_length; - } - - // }}} - // {{{ canSign() - - /** - * Gets whether or not this sub-key can sign data - * - * @return boolean true if this sub-key can sign data and false if this - * sub-key can not sign data. - */ - public function canSign() - { - return $this->_canSign; - } - - // }}} - // {{{ canEncrypt() - - /** - * Gets whether or not this sub-key can encrypt data - * - * @return boolean true if this sub-key can encrypt data and false if this - * sub-key can not encrypt data. - */ - public function canEncrypt() - { - return $this->_canEncrypt; - } - - // }}} - // {{{ hasPrivate() - - /** - * Gets whether or not the private key for this sub-key exists in the - * keyring - * - * @return boolean true the private key for this sub-key exists in the - * keyring and false if it does not. - */ - public function hasPrivate() - { - return $this->_hasPrivate; - } - - // }}} - // {{{ isRevoked() - - /** - * Gets whether or not this sub-key is revoked - * - * @return boolean true if this sub-key is revoked and false if it is not. - */ - public function isRevoked() - { - return $this->_isRevoked; - } - - // }}} - // {{{ setCreationDate() - - /** - * Sets the creation date of this sub-key - * - * The creation date is a Unix timestamp. - * - * @param integer $creationDate the creation date of this sub-key. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setCreationDate($creationDate) - { - $this->_creationDate = intval($creationDate); - return $this; - } - - // }}} - // {{{ setExpirationDate() - - /** - * Sets the expiration date of this sub-key - * - * The expiration date is a Unix timestamp. Specify zero if this sub-key - * does not expire. - * - * @param integer $expirationDate the expiration date of this sub-key. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setExpirationDate($expirationDate) - { - $this->_expirationDate = intval($expirationDate); - return $this; - } - - // }}} - // {{{ setId() - - /** - * Sets the id of this sub-key - * - * @param string $id the id of this sub-key. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setId($id) - { - $this->_id = strval($id); - return $this; - } - - // }}} - // {{{ setAlgorithm() - - /** - * Sets the algorithm used by this sub-key - * - * @param integer $algorithm the algorithm used by this sub-key. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setAlgorithm($algorithm) - { - $this->_algorithm = intval($algorithm); - return $this; - } - - // }}} - // {{{ setFingerprint() - - /** - * Sets the fingerprint of this sub-key - * - * @param string $fingerprint the fingerprint of this sub-key. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setFingerprint($fingerprint) - { - $this->_fingerprint = strval($fingerprint); - return $this; - } - - // }}} - // {{{ setLength() - - /** - * Sets the length of this sub-key in bits - * - * @param integer $length the length of this sub-key in bits. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setLength($length) - { - $this->_length = intval($length); - return $this; - } - - // }}} - // {{{ setCanSign() - - /** - * Sets whether of not this sub-key can sign data - * - * @param boolean $canSign true if this sub-key can sign data and false if - * it can not. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setCanSign($canSign) - { - $this->_canSign = ($canSign) ? true : false; - return $this; - } - - // }}} - // {{{ setCanEncrypt() - - /** - * Sets whether of not this sub-key can encrypt data - * - * @param boolean $canEncrypt true if this sub-key can encrypt data and - * false if it can not. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setCanEncrypt($canEncrypt) - { - $this->_canEncrypt = ($canEncrypt) ? true : false; - return $this; - } - - // }}} - // {{{ setHasPrivate() - - /** - * Sets whether of not the private key for this sub-key exists in the - * keyring - * - * @param boolean $hasPrivate true if the private key for this sub-key - * exists in the keyring and false if it does - * not. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setHasPrivate($hasPrivate) - { - $this->_hasPrivate = ($hasPrivate) ? true : false; - return $this; - } - - // }}} - // {{{ setRevoked() - - /** - * Sets whether or not this sub-key is revoked - * - * @param boolean $isRevoked whether or not this sub-key is revoked. - * - * @return Crypt_GPG_SubKey the current object, for fluent interface. - */ - public function setRevoked($isRevoked) - { - $this->_isRevoked = ($isRevoked) ? true : false; - return $this; - } - - // }}} - // {{{ parse() - - /** - * Parses a sub-key object from a sub-key string - * - * See doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG distribution} for information - * on how the sub-key string is parsed. - * - * @param string $string the string containing the sub-key. - * - * @return Crypt_GPG_SubKey the sub-key object parsed from the string. - */ - public static function parse($string) - { - $tokens = explode(':', $string); - - $subKey = new Crypt_GPG_SubKey(); - - $subKey->setId($tokens[4]); - $subKey->setLength($tokens[2]); - $subKey->setAlgorithm($tokens[3]); - $subKey->setCreationDate(self::_parseDate($tokens[5])); - $subKey->setExpirationDate(self::_parseDate($tokens[6])); - - if ($tokens[1] == 'r') { - $subKey->setRevoked(true); - } - - if (strpos($tokens[11], 's') !== false) { - $subKey->setCanSign(true); - } - - if (strpos($tokens[11], 'e') !== false) { - $subKey->setCanEncrypt(true); - } - - return $subKey; - } - - // }}} - // {{{ _parseDate() - - /** - * Parses a date string as provided by GPG into a UNIX timestamp - * - * @param string $string the date string. - * - * @return integer the UNIX timestamp corresponding to the provided date - * string. - */ - private static function _parseDate($string) - { - if ($string == '') { - $timestamp = 0; - } else { - // all times are in UTC according to GPG documentation - $timeZone = new DateTimeZone('UTC'); - - if (strpos($string, 'T') === false) { - // interpret as UNIX timestamp - $string = '@' . $string; - } - - $date = new DateTime($string, $timeZone); - - // convert to UNIX timestamp - $timestamp = intval($date->format('U')); - } - - return $timestamp; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/UserId.php b/program/lib/Crypt/GPG/UserId.php deleted file mode 100644 index a367bceb3..000000000 --- a/program/lib/Crypt/GPG/UserId.php +++ /dev/null @@ -1,373 +0,0 @@ - - * @copyright 2008-2010 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - */ - -// {{{ class Crypt_GPG_UserId - -/** - * A class for GPG user id information - * - * This class is used to store the results of the {@link Crypt_GPG::getKeys()} - * method. User id objects are members of a {@link Crypt_GPG_Key} object. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2008-2010 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @see Crypt_GPG::getKeys() - * @see Crypt_GPG_Key::getUserIds() - */ -class Crypt_GPG_UserId -{ - // {{{ class properties - - /** - * The name field of this user id - * - * @var string - */ - private $_name = ''; - - /** - * The comment field of this user id - * - * @var string - */ - private $_comment = ''; - - /** - * The email field of this user id - * - * @var string - */ - private $_email = ''; - - /** - * Whether or not this user id is revoked - * - * @var boolean - */ - private $_isRevoked = false; - - /** - * Whether or not this user id is valid - * - * @var boolean - */ - private $_isValid = true; - - // }}} - // {{{ __construct() - - /** - * Creates a new user id - * - * User ids can be initialized from an array of named values. Available - * names are: - * - * - string name - the name field of the user id. - * - string comment - the comment field of the user id. - * - string email - the email field of the user id. - * - boolean valid - whether or not the user id is valid. - * - boolean revoked - whether or not the user id is revoked. - * - * @param Crypt_GPG_UserId|string|array $userId optional. Either an - * existing user id object, which is copied; a user id string, which - * is parsed; or an array of initial values. - */ - public function __construct($userId = null) - { - // parse from string - if (is_string($userId)) { - $userId = self::parse($userId); - } - - // copy from object - if ($userId instanceof Crypt_GPG_UserId) { - $this->_name = $userId->_name; - $this->_comment = $userId->_comment; - $this->_email = $userId->_email; - $this->_isRevoked = $userId->_isRevoked; - $this->_isValid = $userId->_isValid; - } - - // initialize from array - if (is_array($userId)) { - if (array_key_exists('name', $userId)) { - $this->setName($userId['name']); - } - - if (array_key_exists('comment', $userId)) { - $this->setComment($userId['comment']); - } - - if (array_key_exists('email', $userId)) { - $this->setEmail($userId['email']); - } - - if (array_key_exists('revoked', $userId)) { - $this->setRevoked($userId['revoked']); - } - - if (array_key_exists('valid', $userId)) { - $this->setValid($userId['valid']); - } - } - } - - // }}} - // {{{ getName() - - /** - * Gets the name field of this user id - * - * @return string the name field of this user id. - */ - public function getName() - { - return $this->_name; - } - - // }}} - // {{{ getComment() - - /** - * Gets the comments field of this user id - * - * @return string the comments field of this user id. - */ - public function getComment() - { - return $this->_comment; - } - - // }}} - // {{{ getEmail() - - /** - * Gets the email field of this user id - * - * @return string the email field of this user id. - */ - public function getEmail() - { - return $this->_email; - } - - // }}} - // {{{ isRevoked() - - /** - * Gets whether or not this user id is revoked - * - * @return boolean true if this user id is revoked and false if it is not. - */ - public function isRevoked() - { - return $this->_isRevoked; - } - - // }}} - // {{{ isValid() - - /** - * Gets whether or not this user id is valid - * - * @return boolean true if this user id is valid and false if it is not. - */ - public function isValid() - { - return $this->_isValid; - } - - // }}} - // {{{ __toString() - - /** - * Gets a string representation of this user id - * - * The string is formatted as: - * name (comment) . - * - * @return string a string representation of this user id. - */ - public function __toString() - { - $components = array(); - - if (strlen($this->_name) > 0) { - $components[] = $this->_name; - } - - if (strlen($this->_comment) > 0) { - $components[] = '(' . $this->_comment . ')'; - } - - if (strlen($this->_email) > 0) { - $components[] = '<' . $this->_email. '>'; - } - - return implode(' ', $components); - } - - // }}} - // {{{ setName() - - /** - * Sets the name field of this user id - * - * @param string $name the name field of this user id. - * - * @return Crypt_GPG_UserId the current object, for fluent interface. - */ - public function setName($name) - { - $this->_name = strval($name); - return $this; - } - - // }}} - // {{{ setComment() - - /** - * Sets the comment field of this user id - * - * @param string $comment the comment field of this user id. - * - * @return Crypt_GPG_UserId the current object, for fluent interface. - */ - public function setComment($comment) - { - $this->_comment = strval($comment); - return $this; - } - - // }}} - // {{{ setEmail() - - /** - * Sets the email field of this user id - * - * @param string $email the email field of this user id. - * - * @return Crypt_GPG_UserId the current object, for fluent interface. - */ - public function setEmail($email) - { - $this->_email = strval($email); - return $this; - } - - // }}} - // {{{ setRevoked() - - /** - * Sets whether or not this user id is revoked - * - * @param boolean $isRevoked whether or not this user id is revoked. - * - * @return Crypt_GPG_UserId the current object, for fluent interface. - */ - public function setRevoked($isRevoked) - { - $this->_isRevoked = ($isRevoked) ? true : false; - return $this; - } - - // }}} - // {{{ setValid() - - /** - * Sets whether or not this user id is valid - * - * @param boolean $isValid whether or not this user id is valid. - * - * @return Crypt_GPG_UserId the current object, for fluent interface. - */ - public function setValid($isValid) - { - $this->_isValid = ($isValid) ? true : false; - return $this; - } - - // }}} - // {{{ parse() - - /** - * Parses a user id object from a user id string - * - * A user id string is of the form: - * name (comment) with the comment - * and email-address fields being optional. - * - * @param string $string the user id string to parse. - * - * @return Crypt_GPG_UserId the user id object parsed from the string. - */ - public static function parse($string) - { - $userId = new Crypt_GPG_UserId(); - $email = ''; - $comment = ''; - - // get email address from end of string if it exists - $matches = array(); - if (preg_match('/^(.+?) <([^>]+)>$/', $string, $matches) === 1) { - $string = $matches[1]; - $email = $matches[2]; - } - - // get comment from end of string if it exists - $matches = array(); - if (preg_match('/^(.+?) \(([^\)]+)\)$/', $string, $matches) === 1) { - $string = $matches[1]; - $comment = $matches[2]; - } - - $name = $string; - - $userId->setName($name); - $userId->setComment($comment); - $userId->setEmail($email); - - return $userId; - } - - // }}} -} - -// }}} - -?> diff --git a/program/lib/Crypt/GPG/VerifyStatusHandler.php b/program/lib/Crypt/GPG/VerifyStatusHandler.php deleted file mode 100644 index 8904be149..000000000 --- a/program/lib/Crypt/GPG/VerifyStatusHandler.php +++ /dev/null @@ -1,216 +0,0 @@ - - * @copyright 2008 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id$ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ - -/** - * Signature object class definition - */ -require_once 'Crypt/GPG/Signature.php'; - -/** - * Status line handler for the verify operation - * - * This class is used internally by Crypt_GPG and does not need be used - * directly. See the {@link Crypt_GPG} class for end-user API. - * - * This class is responsible for building signature objects that are returned - * by the {@link Crypt_GPG::verify()} method. See doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG distribution} for detailed - * information on GPG's status output for the verify operation. - * - * @category Encryption - * @package Crypt_GPG - * @author Michael Gauthier - * @copyright 2008 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -class Crypt_GPG_VerifyStatusHandler -{ - // {{{ protected properties - - /** - * The current signature id - * - * Ths signature id is emitted by GPG before the new signature line so we - * must remember it temporarily. - * - * @var string - */ - protected $signatureId = ''; - - /** - * List of parsed {@link Crypt_GPG_Signature} objects - * - * @var array - */ - protected $signatures = array(); - - /** - * Array index of the current signature - * - * @var integer - */ - protected $index = -1; - - // }}} - // {{{ handle() - - /** - * Handles a status line - * - * @param string $line the status line to handle. - * - * @return void - */ - public function handle($line) - { - $tokens = explode(' ', $line); - switch ($tokens[0]) { - case 'GOODSIG': - case 'EXPSIG': - case 'EXPKEYSIG': - case 'REVKEYSIG': - case 'BADSIG': - $signature = new Crypt_GPG_Signature(); - - // if there was a signature id, set it on the new signature - if ($this->signatureId != '') { - $signature->setId($this->signatureId); - $this->signatureId = ''; - } - - // Detect whether fingerprint or key id was returned and set - // signature values appropriately. Key ids are strings of either - // 16 or 8 hexadecimal characters. Fingerprints are strings of 40 - // hexadecimal characters. The key id is the last 16 characters of - // the key fingerprint. - if (strlen($tokens[1]) > 16) { - $signature->setKeyFingerprint($tokens[1]); - $signature->setKeyId(substr($tokens[1], -16)); - } else { - $signature->setKeyId($tokens[1]); - } - - // get user id string - $string = implode(' ', array_splice($tokens, 2)); - $string = rawurldecode($string); - - $signature->setUserId(Crypt_GPG_UserId::parse($string)); - - $this->index++; - $this->signatures[$this->index] = $signature; - break; - - case 'ERRSIG': - $signature = new Crypt_GPG_Signature(); - - // if there was a signature id, set it on the new signature - if ($this->signatureId != '') { - $signature->setId($this->signatureId); - $this->signatureId = ''; - } - - // Detect whether fingerprint or key id was returned and set - // signature values appropriately. Key ids are strings of either - // 16 or 8 hexadecimal characters. Fingerprints are strings of 40 - // hexadecimal characters. The key id is the last 16 characters of - // the key fingerprint. - if (strlen($tokens[1]) > 16) { - $signature->setKeyFingerprint($tokens[1]); - $signature->setKeyId(substr($tokens[1], -16)); - } else { - $signature->setKeyId($tokens[1]); - } - - $this->index++; - $this->signatures[$this->index] = $signature; - - break; - - case 'VALIDSIG': - if (!array_key_exists($this->index, $this->signatures)) { - break; - } - - $signature = $this->signatures[$this->index]; - - $signature->setValid(true); - $signature->setKeyFingerprint($tokens[1]); - - if (strpos($tokens[3], 'T') === false) { - $signature->setCreationDate($tokens[3]); - } else { - $signature->setCreationDate(strtotime($tokens[3])); - } - - if (array_key_exists(4, $tokens)) { - if (strpos($tokens[4], 'T') === false) { - $signature->setExpirationDate($tokens[4]); - } else { - $signature->setExpirationDate(strtotime($tokens[4])); - } - } - - break; - - case 'SIG_ID': - // note: signature id comes before new signature line and may not - // exist for some signature types - $this->signatureId = $tokens[1]; - break; - } - } - - // }}} - // {{{ getSignatures() - - /** - * Gets the {@link Crypt_GPG_Signature} objects parsed by this handler - * - * @return array the signature objects parsed by this handler. - */ - public function getSignatures() - { - return $this->signatures; - } - - // }}} -} - -?> diff --git a/program/lib/Crypt/GPGAbstract.php b/program/lib/Crypt/GPGAbstract.php deleted file mode 100644 index 214133936..000000000 --- a/program/lib/Crypt/GPGAbstract.php +++ /dev/null @@ -1,508 +0,0 @@ - - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: GPG.php 305428 2010-11-17 02:47:56Z gauthierm $ - * @link http://pear.php.net/package/Crypt_GPG - * @link http://pear.php.net/manual/en/package.encryption.crypt-gpg.php - * @link http://www.gnupg.org/ - */ - -/** - * GPG key class - */ -require_once 'Crypt/GPG/Key.php'; - -/** - * GPG sub-key class - */ -require_once 'Crypt/GPG/SubKey.php'; - -/** - * GPG user id class - */ -require_once 'Crypt/GPG/UserId.php'; - -/** - * GPG process and I/O engine class - */ -require_once 'Crypt/GPG/Engine.php'; - -/** - * GPG exception classes - */ -require_once 'Crypt/GPG/Exceptions.php'; - -// {{{ class Crypt_GPGAbstract - -/** - * Base class for implementing a user of {@link Crypt_GPG_Engine} - * - * @category Encryption - * @package Crypt_GPG - * @author Nathan Fredrickson - * @author Michael Gauthier - * @copyright 2005-2013 silverorange - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @link http://pear.php.net/package/Crypt_GPG - * @link http://www.gnupg.org/ - */ -abstract class Crypt_GPGAbstract -{ - // {{{ class error constants - - /** - * Error code returned when there is no error. - */ - const ERROR_NONE = 0; - - /** - * Error code returned when an unknown or unhandled error occurs. - */ - const ERROR_UNKNOWN = 1; - - /** - * Error code returned when a bad passphrase is used. - */ - const ERROR_BAD_PASSPHRASE = 2; - - /** - * Error code returned when a required passphrase is missing. - */ - const ERROR_MISSING_PASSPHRASE = 3; - - /** - * Error code returned when a key that is already in the keyring is - * imported. - */ - const ERROR_DUPLICATE_KEY = 4; - - /** - * Error code returned the required data is missing for an operation. - * - * This could be missing key data, missing encrypted data or missing - * signature data. - */ - const ERROR_NO_DATA = 5; - - /** - * Error code returned when an unsigned key is used. - */ - const ERROR_UNSIGNED_KEY = 6; - - /** - * Error code returned when a key that is not self-signed is used. - */ - const ERROR_NOT_SELF_SIGNED = 7; - - /** - * Error code returned when a public or private key that is not in the - * keyring is used. - */ - const ERROR_KEY_NOT_FOUND = 8; - - /** - * Error code returned when an attempt to delete public key having a - * private key is made. - */ - const ERROR_DELETE_PRIVATE_KEY = 9; - - /** - * Error code returned when one or more bad signatures are detected. - */ - const ERROR_BAD_SIGNATURE = 10; - - /** - * Error code returned when there is a problem reading GnuPG data files. - */ - const ERROR_FILE_PERMISSIONS = 11; - - /** - * Error code returned when a key could not be created. - */ - const ERROR_KEY_NOT_CREATED = 12; - - /** - * Error code returned when bad key parameters are used during key - * generation. - */ - const ERROR_BAD_KEY_PARAMS = 13; - - // }}} - // {{{ other class constants - - /** - * URI at which package bugs may be reported. - */ - const BUG_URI = 'http://pear.php.net/bugs/report.php?package=Crypt_GPG'; - - // }}} - // {{{ protected class properties - - /** - * Engine used to control the GPG subprocess - * - * @var Crypt_GPG_Engine - * - * @see Crypt_GPGAbstract::setEngine() - */ - protected $engine = null; - - // }}} - // {{{ __construct() - - /** - * Creates a new GPG object - * - * Available options are: - * - * - string homedir - the directory where the GPG - * keyring files are stored. If not - * specified, Crypt_GPG uses the - * default of ~/.gnupg. - * - string publicKeyring - the file path of the public - * keyring. Use this if the public - * keyring is not in the homedir, or - * if the keyring is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * keyring with this option - * (/foo/bar/pubring.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string privateKeyring - the file path of the private - * keyring. Use this if the private - * keyring is not in the homedir, or - * if the keyring is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * keyring with this option - * (/foo/bar/secring.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string trustDb - the file path of the web-of-trust - * database. Use this if the trust - * database is not in the homedir, or - * if the database is in a directory - * not writable by the process - * invoking GPG (like Apache). Then - * you can specify the path to the - * trust database with this option - * (/foo/bar/trustdb.gpg), and specify - * a writable directory (like /tmp) - * using the homedir option. - * - string binary - the location of the GPG binary. If - * not specified, the driver attempts - * to auto-detect the GPG binary - * location using a list of known - * default locations for the current - * operating system. The option - * gpgBinary is a - * deprecated alias for this option. - * - string agent - the location of the GnuPG agent - * binary. The gpg-agent is only - * used for GnuPG 2.x. If not - * specified, the engine attempts - * to auto-detect the gpg-agent - * binary location using a list of - * know default locations for the - * current operating system. - * - boolean debug - whether or not to use debug mode. - * When debug mode is on, all - * communication to and from the GPG - * subprocess is logged. This can be - * - * @param array $options optional. An array of options used to create the - * GPG object. All options are optional and are - * represented as key-value pairs. - * - * @throws Crypt_GPG_FileException if the homedir does not exist - * and cannot be created. This can happen if homedir is - * not specified, Crypt_GPG is run as the web user, and the web - * user has no home directory. This exception is also thrown if any - * of the options publicKeyring, - * privateKeyring or trustDb options are - * specified but the files do not exist or are are not readable. - * This can happen if the user running the Crypt_GPG process (for - * example, the Apache user) does not have permission to read the - * files. - * - * @throws PEAR_Exception if the provided binary is invalid, or - * if no binary is provided and no suitable binary could - * be found. - * - * @throws PEAR_Exception if the provided agent is invalid, or - * if no agent is provided and no suitable gpg-agent - * cound be found. - */ - public function __construct(array $options = array()) - { - $this->setEngine(new Crypt_GPG_Engine($options)); - } - - // }}} - // {{{ setEngine() - - /** - * Sets the I/O engine to use for GnuPG operations - * - * Normally this method does not need to be used. It provides a means for - * dependency injection. - * - * @param Crypt_GPG_Engine $engine the engine to use. - * - * @return Crypt_GPGAbstract the current object, for fluent interface. - */ - public function setEngine(Crypt_GPG_Engine $engine) - { - $this->engine = $engine; - return $this; - } - - // }}} - // {{{ _getKeys() - - /** - * Gets the available keys in the keyring - * - * Calls GPG with the --list-keys command and grabs keys. See - * the first section of doc/DETAILS in the - * {@link http://www.gnupg.org/download/ GPG package} for a detailed - * description of how the GPG command output is parsed. - * - * @param string $keyId optional. Only keys with that match the specified - * pattern are returned. The pattern may be part of - * a user id, a key id or a key fingerprint. If not - * specified, all keys are returned. - * - * @return array an array of {@link Crypt_GPG_Key} objects. If no keys - * match the specified $keyId an empty array is - * returned. - * - * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs. - * Use the debug option and file a bug report if these - * exceptions occur. - * - * @see Crypt_GPG_Key - */ - protected function _getKeys($keyId = '') - { - // get private key fingerprints - if ($keyId == '') { - $operation = '--list-secret-keys'; - } else { - $operation = '--list-secret-keys ' . escapeshellarg($keyId); - } - - // According to The file 'doc/DETAILS' in the GnuPG distribution, using - // double '--with-fingerprint' also prints the fingerprint for subkeys. - $arguments = array( - '--with-colons', - '--with-fingerprint', - '--with-fingerprint', - '--fixed-list-mode' - ); - - $output = ''; - - $this->engine->reset(); - $this->engine->setOutput($output); - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - case self::ERROR_KEY_NOT_FOUND: - // ignore not found key errors - break; - case self::ERROR_FILE_PERMISSIONS: - $filename = $this->engine->getErrorFilename(); - if ($filename) { - throw new Crypt_GPG_FileException( - sprintf( - 'Error reading GnuPG data file \'%s\'. Check to make ' . - 'sure it is readable by the current user.', - $filename - ), - $code, - $filename - ); - } - throw new Crypt_GPG_FileException( - 'Error reading GnuPG data file. Check to make GnuPG data ' . - 'files are readable by the current user.', - $code - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error getting keys. Please use the \'debug\' option ' . - 'when creating the Crypt_GPG object, and file a bug report ' . - 'at ' . self::BUG_URI, - $code - ); - } - - $privateKeyFingerprints = array(); - - $lines = explode(PHP_EOL, $output); - foreach ($lines as $line) { - $lineExp = explode(':', $line); - if ($lineExp[0] == 'fpr') { - $privateKeyFingerprints[] = $lineExp[9]; - } - } - - // get public keys - if ($keyId == '') { - $operation = '--list-public-keys'; - } else { - $operation = '--list-public-keys ' . escapeshellarg($keyId); - } - - $output = ''; - - $this->engine->reset(); - $this->engine->setOutput($output); - $this->engine->setOperation($operation, $arguments); - $this->engine->run(); - - $code = $this->engine->getErrorCode(); - - switch ($code) { - case self::ERROR_NONE: - case self::ERROR_KEY_NOT_FOUND: - // ignore not found key errors - break; - case self::ERROR_FILE_PERMISSIONS: - $filename = $this->engine->getErrorFilename(); - if ($filename) { - throw new Crypt_GPG_FileException( - sprintf( - 'Error reading GnuPG data file \'%s\'. Check to make ' . - 'sure it is readable by the current user.', - $filename - ), - $code, - $filename - ); - } - throw new Crypt_GPG_FileException( - 'Error reading GnuPG data file. Check to make GnuPG data ' . - 'files are readable by the current user.', - $code - ); - default: - throw new Crypt_GPG_Exception( - 'Unknown error getting keys. Please use the \'debug\' option ' . - 'when creating the Crypt_GPG object, and file a bug report ' . - 'at ' . self::BUG_URI, - $code - ); - } - - $keys = array(); - - $key = null; // current key - $subKey = null; // current sub-key - - $lines = explode(PHP_EOL, $output); - foreach ($lines as $line) { - $lineExp = explode(':', $line); - - if ($lineExp[0] == 'pub') { - - // new primary key means last key should be added to the array - if ($key !== null) { - $keys[] = $key; - } - - $key = new Crypt_GPG_Key(); - - $subKey = Crypt_GPG_SubKey::parse($line); - $key->addSubKey($subKey); - - } elseif ($lineExp[0] == 'sub') { - - $subKey = Crypt_GPG_SubKey::parse($line); - $key->addSubKey($subKey); - - } elseif ($lineExp[0] == 'fpr') { - - $fingerprint = $lineExp[9]; - - // set current sub-key fingerprint - $subKey->setFingerprint($fingerprint); - - // if private key exists, set has private to true - if (in_array($fingerprint, $privateKeyFingerprints)) { - $subKey->setHasPrivate(true); - } - - } elseif ($lineExp[0] == 'uid') { - - $string = stripcslashes($lineExp[9]); // as per documentation - $userId = new Crypt_GPG_UserId($string); - - if ($lineExp[1] == 'r') { - $userId->setRevoked(true); - } - - $key->addUserId($userId); - - } - } - - // add last key - if ($key !== null) { - $keys[] = $key; - } - - return $keys; - } - - // }}} -} - -// }}} - -?> -- cgit v1.2.3