package.xml 0000664 0001750 0001750 00000122467 12242643672 011323 0 ustar jan jan
* - http: (Horde_Http_Client) The HTTP client object to use. * - keyserver: (string) The public PGP keyserver to use. * - port: (integer) The public PGP keyserver port. **/ public function __construct(Horde_Crypt_Pgp $pgp, array $params = array()) { $this->_pgp = $pgp; $this->_http = (isset($params['http']) && ($params['http'] instanceof Horde_Http_Client)) ? $params['http'] : new Horde_Http_Client(); $this->_keyserver = isset($params['keyserver']) ? $params['keyserver'] : 'pool.sks-keyservers.net'; $this->_keyserver .= ':' . (isset($params['port']) ? $params['port'] : '11371'); } /** * Returns PGP public key data retrieved from a public keyserver. * * @param string $keyid The key ID of the PGP key. * * @return string The PGP public key. * @throws Horde_Crypt_Exception */ public function get($keyid) { /* Connect to the public keyserver. */ $url = $this->_createUrl('/pks/lookup', array( 'op' => 'get', 'search' => $this->_pgp->getKeyIDString($keyid) )); try { $output = $this->_http->get($url)->getBody(); } catch (Horde_Http_Exception $e) { throw new Horde_Crypt_Exception($e); } /* Grab PGP key from output. */ if (($start = strstr($output, '-----BEGIN'))) { $length = strpos($start, '-----END') + 34; return substr($start, 0, $length); } throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not obtain public key from the keyserver.")); } /** * Sends a PGP public key to a public keyserver. * * @param string $pubkey The PGP public key * * @throws Horde_Crypt_Exception */ public function put($pubkey) { /* Get the key ID of the public key. */ $info = $this->_pgp->pgpPacketInformation($pubkey); /* See if the public key already exists on the keyserver. */ try { $this->get($info['keyid']); } catch (Horde_Crypt_Exception $e) { $pubkey = 'keytext=' . urlencode(rtrim($pubkey)); try { $this->_http->post( $this->_createUrl('/pks/add'), $pubkey, array( 'User-Agent: Horde Application Framework', 'Content-Type: application/x-www-form-urlencoded', 'Content-Length: ' . strlen($pubkey), 'Connection: close' ) ); } catch (Horde_Http_Exception $e) { throw new Horde_Crypt_Exception($e); } } throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Key already exists on the public keyserver.")); } /** * Returns the first matching key ID for an email address from a public * keyserver. * * @param string $address The email address of the PGP key. * * @return string The PGP key ID. * @throws Horde_Crypt_Exception */ public function getKeyId($address) { $pubkey = null; /* Connect to the public keyserver. */ $url = $this->_createUrl('/pks/lookup', array( 'op' => 'index', 'options' => 'mr', 'search' => $address )); try { $output = $this->_http->get($url)->getBody(); } catch (Horde_Http_Exception $e) { throw new Horde_Crypt_Exception($e); } if (strpos($output, '-----BEGIN PGP PUBLIC KEY BLOCK') !== false) { $pubkey = $output; } elseif (strpos($output, 'pub:') !== false) { $output = explode("\n", $output); $keyids = $keyuids = array(); $curid = null; foreach ($output as $line) { if (substr($line, 0, 4) == 'pub:') { $line = explode(':', $line); /* Ignore invalid lines and expired keys. */ if (count($line) != 7 || (!empty($line[5]) && $line[5] <= time())) { continue; } $curid = $line[4]; $keyids[$curid] = $line[1]; } elseif (!is_null($curid) && substr($line, 0, 4) == 'uid:') { preg_match("/<([^>]+)>/", $line, $matches); $keyuids[$curid][] = $matches[1]; } } /* Remove keys without a matching UID. */ foreach ($keyuids as $id => $uids) { $match = false; foreach ($uids as $uid) { if ($uid == $address) { $match = true; break; } } if (!$match) { unset($keyids[$id]); } } /* Sort by timestamp to use the newest key. */ if (count($keyids)) { ksort($keyids); $pubkey = $this->get(array_pop($keyids)); } } if ($pubkey) { $sig = $this->_pgp->pgpPacketSignature($pubkey, $address); if (!empty($sig['keyid']) && (empty($sig['public_key']['expires']) || $sig['public_key']['expires'] > time())) { return substr($this->_pgp->getKeyIDString($sig['keyid']), 2); } } throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not obtain public key from the keyserver.")); } /** * Create the URL for the keyserver. * * @param string $uri Action URI. * @param array $params List of parameters to add to URL. * * @return Horde_Url Keyserver URL. */ protected function _createUrl($uri, array $params = array()) { $url = new Horde_Url($this->_keyserver . $uri, true); return $url->add($params); } } Horde_Crypt-2.4.0/lib/Horde/Crypt/Pgp/Parse.php 0000664 0001750 0001750 00000017466 12242643672 017312 0 ustar jan jan * @category Horde * @copyright 2002-2013 Horde LLC * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Crypt * @since 2.4.0 */ class Horde_Crypt_Pgp_Parse { /** * Armor Header Lines - From RFC 2440: * * An Armor Header Line consists of the appropriate header line text * surrounded by five (5) dashes ('-', 0x2D) on either side of the header * line text. The header line text is chosen based upon the type of data * that is being encoded in Armor, and how it is being encoded. * * All Armor Header Lines are prefixed with 'PGP'. * * The Armor Tail Line is composed in the same manner as the Armor Header * Line, except the string "BEGIN" is replaced by the string "END." */ /* Used for signed, encrypted, or compressed files. */ const ARMOR_MESSAGE = 1; /* Used for signed files. */ const ARMOR_SIGNED_MESSAGE = 2; /* Used for armoring public keys. */ const ARMOR_PUBLIC_KEY = 3; /* Used for armoring private keys. */ const ARMOR_PRIVATE_KEY = 4; /* Used for detached signatures, PGP/MIME signatures, and natures * following clearsigned messages. */ const ARMOR_SIGNATURE = 5; /* Regular text contained in an PGP message. */ const ARMOR_TEXT = 6; /** * Metadata names for signature data. */ const SIG_CHARSET = 'pgp_sig_charset'; const SIG_RAW = 'pgp_sig_raw'; /** * Strings in armor header lines used to distinguish between the different * types of PGP decryption/encryption. * * @var array */ protected $_armor = array( 'MESSAGE' => self::ARMOR_MESSAGE, 'SIGNED MESSAGE' => self::ARMOR_SIGNED_MESSAGE, 'PUBLIC KEY BLOCK' => self::ARMOR_PUBLIC_KEY, 'PRIVATE KEY BLOCK' => self::ARMOR_PRIVATE_KEY, 'SIGNATURE' => self::ARMOR_SIGNATURE ); /** * Parses a message into text and PGP components. * * @param mixed $text Either the text to parse or a Horde_Stream object. * * @return array An array with the parsed text, returned in blocks of * text corresponding to their actual order. Keys: *
* - data: (array) The data for each section. Each line has been * stripped of EOL characters. * - type: (integer) The type of data contained in block. Valid types * are the class ARMOR_* constants. **/ public function parse($text) { $data = array(); $temp = array( 'type' => self::ARMOR_TEXT ); if ($text instanceof Horde_Stream) { $stream = $text; $stream->rewind(); } else { $stream = new Horde_Stream_Temp(); $stream->add($text, true); } while (!$stream->eof()) { $val = rtrim($stream->getToChar("\n", false), "\r"); if (preg_match('/^-----(BEGIN|END) PGP ([^-]+)-----\s*$/', $val, $matches)) { if (isset($temp['data'])) { $data[] = $temp; } $temp = array(); if ($matches[1] == 'BEGIN') { $temp['type'] = $this->_armor[$matches[2]]; $temp['data'][] = $val; } elseif ($matches[1] == 'END') { $temp['type'] = self::ARMOR_TEXT; $data[count($data) - 1]['data'][] = $val; } } else { $temp['data'][] = $val; } } if (isset($temp['data']) && ((count($temp['data']) > 1) || !empty($temp['data'][0]))) { $data[] = $temp; } return $data; } /** * Parses an armored message into a Horde_Mime_Part object. * * @param mixed $text Either the text to parse or a Horde_Stream object. * * @return mixed Either null if no PGP data was found, or a * Horde_Mime_Part object. For detached signature data: * the full contents of the armored text (data + sig) is * contained in the SIG_RAW metadata, and the charset is * contained in the SIG_CHARSET metadata, within the * application/pgp-signature part. */ public function parseToPart($text, $charset = 'UTF-8') { $parts = $this->parse($text); if (empty($parts) || ((count($parts) == 1) && ($parts[0]['type'] == self::ARMOR_TEXT))) { return null; } $new_part = new Horde_Mime_Part(); $new_part->setType('multipart/mixed'); foreach ($parts as $val) { switch ($val['type']) { case self::ARMOR_TEXT: $part = new Horde_Mime_Part(); $part->setType('text/plain'); $part->setCharset($charset); $part->setContents(implode("\n", $val['data'])); $new_part->addPart($part); break; case self::ARMOR_PUBLIC_KEY: $part = new Horde_Mime_Part(); $part->setType('application/pgp-keys'); $part->setContents(implode("\n", $val['data'])); $new_part->addPart($part); break; case self::ARMOR_MESSAGE: $part = new Horde_Mime_Part(); $part->setType('multipart/encrypted'); $part->setMetadata(IMP_Mime_Viewer_Pgp::PGP_ARMOR, true); $part->setContentTypeParameter('protocol', 'application/pgp-encrypted'); $part1 = new Horde_Mime_Part(); $part1->setType('application/pgp-encrypted'); $part1->setContents("Version: 1\n"); $part2 = new Horde_Mime_Part(); $part2->setType('application/octet-stream'); $part2->setContents(implode("\n", $val['data'])); $part2->setDisposition('inline'); $part->addPart($part1); $part->addPart($part2); $new_part->addPart($part); break; case self::ARMOR_SIGNED_MESSAGE: if (($sig = current($parts)) && ($sig['type'] == self::ARMOR_SIGNATURE)) { $part = new Horde_Mime_Part(); $part->setType('multipart/signed'); // TODO: add micalg parameter $part->setContentTypeParameter('protocol', 'application/pgp-signature'); $part1 = new Horde_Mime_Part(); $part1->setType('text/plain'); $part1->setCharset($charset); $part1_data = implode("\n", $val['data']); $part1->setContents(substr($part1_data, strpos($part1_data, "\n\n") + 2)); $part2 = new Horde_Mime_Part(); $part2->setType('application/pgp-signature'); $part2->setContents(implode("\n", $sig['data'])); $part2->setMetadata(self::SIG_CHARSET, $charset); $part2->setMetadata(self::SIG_RAW, implode("\n", $val['data']) . "\n" . implode("\n", $sig['data'])); $part->addPart($part1); $part->addPart($part2); $new_part->addPart($part); next($parts); } } } return $new_part; } } Horde_Crypt-2.4.0/lib/Horde/Crypt/Exception.php 0000664 0001750 0001750 00000000744 12242643672 017437 0 ustar jan jan * @category Horde * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Crypt */ class Horde_Crypt_Exception extends Horde_Exception_Wrapped { } Horde_Crypt-2.4.0/lib/Horde/Crypt/Pgp.php 0000664 0001750 0001750 00000154132 12242643672 016230 0 ustar jan jan * @category Horde * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Crypt */ /** * Horde_Crypt_Pgp:: provides a framework for Horde applications to interact * with the GNU Privacy Guard program ("GnuPG"). GnuPG implements the OpenPGP * standard (RFC 2440). * * GnuPG Website: http://www.gnupg.org/ * * This class has been developed with, and is only guaranteed to work with, * Version 1.21 or above of GnuPG. * * @author Michael Slusarz
* 'program' - (string) [REQUIRED] The path to the GnuPG binary. * 'proxy_host - (string) Proxy host. (@deprecated) * 'proxy_port - (integer) Proxy port. (@deprecated) ** * @throws InvalidArgumentException */ public function __construct($params = array()) { parent::__construct($params); if (empty($params['program'])) { throw new InvalidArgumentException('The location of the GnuPG binary must be given to the Horde_Crypt_Pgp:: class.'); } /* Store the location of GnuPG and set common options. */ $this->_gnupg = array( $params['program'], '--no-tty', '--no-secmem-warning', '--no-options', '--no-default-keyring', '--yes', '--homedir ' . $this->_tempdir ); if (strncasecmp(PHP_OS, 'WIN', 3)) { array_unshift($this->_gnupg, 'LANG= ;'); } $this->_params = $params; } /** * Generates a personal Public/Private keypair combination. * * @param string $realname The name to use for the key. * @param string $email The email to use for the key. * @param string $passphrase The passphrase to use for the key. * @param string $comment The comment to use for the key. * @param integer $keylength The keylength to use for the key. * @param integer $expire The expiration date (UNIX timestamp). No * expiration if empty. * @param string $key_type Key type (since 2.2.0). * @param string $subkey_type Subkey type (since 2.2.0). * * @return array An array consisting of: *
* Key Value * -------------------------- * 'public' => Public Key * 'private' => Private Key ** @throws Horde_Crypt_Exception */ public function generateKey($realname, $email, $passphrase, $comment = '', $keylength = 1024, $expire = null, $key_type = 'RSA', $subkey_type = 'RSA') { /* Create temp files to hold the generated keys. */ $pub_file = $this->_createTempFile('horde-pgp'); $secret_file = $this->_createTempFile('horde-pgp'); $expire = empty($expire) ? 0 : date('Y-m-d', $expire); /* Create the config file necessary for GnuPG to run in batch mode. */ /* TODO: Sanitize input, More user customizable? */ $input = array( '%pubring ' . $pub_file, '%secring ' . $secret_file, 'Key-Type: ' . $key_type, 'Key-Length: ' . $keylength, 'Subkey-Type: ' . $subkey_type, 'Subkey-Length: ' . $keylength, 'Name-Real: ' . $realname, 'Name-Email: ' . $email, 'Expire-Date: ' . $expire, 'Passphrase: ' . $passphrase, 'Preferences: AES256 AES192 AES CAST5 3DES SHA256 SHA512 SHA384 SHA224 SHA1 ZLIB BZIP2 ZIP Uncompressed' ); if (!empty($comment)) { $input[] = 'Name-Comment: ' . $comment; } $input[] = '%commit'; /* Run through gpg binary. */ $cmdline = array( '--gen-key', '--batch', '--armor' ); $result = $this->_callGpg($cmdline, 'w', $input, true, true); /* Get the keys from the temp files. */ $public_key = file_get_contents($pub_file); $secret_key = file_get_contents($secret_file); /* If either key is empty, something went wrong. */ if (empty($public_key) || empty($secret_key)) { $msg = Horde_Crypt_Translation::t("Public/Private keypair not generated successfully."); if (!empty($result->stderr)) { $msg .= ' ' . Horde_Crypt_Translation::t("Returned error message:") . ' ' . $result->stderr; } throw new Horde_Crypt_Exception($msg); } return array('public' => $public_key, 'private' => $secret_key); } /** * Returns information on a PGP data block. * * @param string $pgpdata The PGP data block. * * @return array An array with information on the PGP data block. If an * element is not present in the data block, it will * likewise not be set in the array. *
* Array Format: * ------------- * [public_key]/[secret_key] => Array * ( * [created] => Key creation - UNIX timestamp * [expires] => Key expiration - UNIX timestamp (0 = never expires) * [size] => Size of the key in bits * ) * * [keyid] => Key ID of the PGP data (if available) * 16-bit hex value * * [signature] => Array ( * [id{n}/'_SIGNATURE'] => Array ( * [name] => Full Name * [comment] => Comment * [email] => E-mail Address * [keyid] => 16-bit hex value * [created] => Signature creation - UNIX timestamp * [expires] => Signature expiration - UNIX timestamp * [micalg] => The hash used to create the signature * [sig_{hex}] => Array [details of a sig verifying the ID] ( * [created] => Signature creation - UNIX timestamp * [expires] => Signature expiration - UNIX timestamp * [keyid] => 16-bit hex value * [micalg] => The hash used to create the signature * ) * ) * ) ** * Each user ID will be stored in the array 'signature' and have data * associated with it, including an array for information on each * signature that has signed that UID. Signatures not associated with a * UID (e.g. revocation signatures and sub keys) will be stored under the * special keyword '_SIGNATURE'. * * @throws Horde_Crypt_Exception */ public function pgpPacketInformation($pgpdata) { $data_array = array(); $keyid = ''; $header = null; $input = $this->_createTempFile('horde-pgp'); $sig_id = $uid_idx = 0; /* Store message in temporary file. */ file_put_contents($input, $pgpdata); $cmdline = array( '--list-packets', $input ); $result = $this->_callGpg($cmdline, 'r'); foreach (explode("\n", $result->stdout) as $line) { /* Headers are prefaced with a ':' as the first character on the line. */ if (strpos($line, ':') === 0) { $lowerLine = Horde_String::lower($line); /* If we have a key (rather than a signature block), get the key's ID */ if (strpos($lowerLine, ':public key packet:') !== false || strpos($lowerLine, ':secret key packet:') !== false) { $cmdline = array( '--with-colons', $input ); $data = $this->_callGpg($cmdline, 'r'); if (preg_match("/(sec|pub):.*:.*:.*:([A-F0-9]{16}):/", $data->stdout, $matches)) { $keyid = $matches[2]; } } if (strpos($lowerLine, ':public key packet:') !== false) { $header = 'public_key'; } elseif (strpos($lowerLine, ':secret key packet:') !== false) { $header = 'secret_key'; } elseif (strpos($lowerLine, ':user id packet:') !== false) { $uid_idx++; $line = preg_replace_callback('/\\\\x([0-9a-f]{2})/', array($this, '_pgpPacketInformationHelper'), $line); if (preg_match("/\"([^\<]+)\<([^\>]+)\>\"/", $line, $matches)) { $header = 'id' . $uid_idx; if (preg_match('/([^\(]+)\((.+)\)$/', trim($matches[1]), $comment_matches)) { $data_array['signature'][$header]['name'] = trim($comment_matches[1]); $data_array['signature'][$header]['comment'] = $comment_matches[2]; } else { $data_array['signature'][$header]['name'] = trim($matches[1]); $data_array['signature'][$header]['comment'] = ''; } $data_array['signature'][$header]['email'] = $matches[2]; $data_array['signature'][$header]['keyid'] = $keyid; } } elseif (strpos($lowerLine, ':signature packet:') !== false) { if (empty($header) || empty($uid_idx)) { $header = '_SIGNATURE'; } if (preg_match("/keyid\s+([0-9A-F]+)/i", $line, $matches)) { $sig_id = $matches[1]; $data_array['signature'][$header]['sig_' . $sig_id]['keyid'] = $matches[1]; $data_array['keyid'] = $matches[1]; } } elseif (strpos($lowerLine, ':literal data packet:') !== false) { $header = 'literal'; } elseif (strpos($lowerLine, ':encrypted data packet:') !== false) { $header = 'encrypted'; } else { $header = null; } } else { if ($header == 'secret_key' || $header == 'public_key') { if (preg_match("/created\s+(\d+),\s+expires\s+(\d+)/i", $line, $matches)) { $data_array[$header]['created'] = $matches[1]; $data_array[$header]['expires'] = $matches[2]; } elseif (preg_match("/\s+[sp]key\[0\]:\s+\[(\d+)/i", $line, $matches)) { $data_array[$header]['size'] = $matches[1]; } } elseif ($header == 'literal' || $header == 'encrypted') { $data_array[$header] = true; } elseif ($header) { if (preg_match("/version\s+\d+,\s+created\s+(\d+)/i", $line, $matches)) { $data_array['signature'][$header]['sig_' . $sig_id]['created'] = $matches[1]; } elseif (isset($data_array['signature'][$header]['sig_' . $sig_id]['created']) && preg_match('/expires after (\d+y\d+d\d+h\d+m)\)$/', $line, $matches)) { $expires = $matches[1]; preg_match('/^(\d+)y(\d+)d(\d+)h(\d+)m$/', $expires, $matches); list(, $years, $days, $hours, $minutes) = $matches; $data_array['signature'][$header]['sig_' . $sig_id]['expires'] = strtotime('+ ' . $years . ' years + ' . $days . ' days + ' . $hours . ' hours + ' . $minutes . ' minutes', $data_array['signature'][$header]['sig_' . $sig_id]['created']); } elseif (preg_match("/digest algo\s+(\d{1})/", $line, $matches)) { $micalg = $this->_hashAlg[$matches[1]]; $data_array['signature'][$header]['sig_' . $sig_id]['micalg'] = $micalg; if ($header == '_SIGNATURE') { /* Likely a signature block, not a key. */ $data_array['signature']['_SIGNATURE']['micalg'] = $micalg; } if ($sig_id == $keyid) { /* Self signing signature - we can assume * the micalg value from this signature is * that for the key */ $data_array['signature']['_SIGNATURE']['micalg'] = $micalg; $data_array['signature'][$header]['micalg'] = $micalg; } } } } } $keyid && $data_array['keyid'] = $keyid; return $data_array; } /** * TODO */ protected function _pgpPacketInformationHelper($a) { return chr(hexdec($a[1])); } /** * Returns human readable information on a PGP key. * * @param string $pgpdata The PGP data block. * * @return string Tabular information on the PGP key. * @throws Horde_Crypt_Exception */ public function pgpPrettyKey($pgpdata) { $msg = ''; $packet_info = $this->pgpPacketInformation($pgpdata); $fingerprints = $this->getFingerprintsFromKey($pgpdata); if (!empty($packet_info['signature'])) { /* Making the property names the same width for all * localizations .*/ $leftrow = array( Horde_Crypt_Translation::t("Name"), Horde_Crypt_Translation::t("Key Type"), Horde_Crypt_Translation::t("Key Creation"), Horde_Crypt_Translation::t("Expiration Date"), Horde_Crypt_Translation::t("Key Length"), Horde_Crypt_Translation::t("Comment"), Horde_Crypt_Translation::t("E-Mail"), Horde_Crypt_Translation::t("Hash-Algorithm"), Horde_Crypt_Translation::t("Key ID"), Horde_Crypt_Translation::t("Key Fingerprint") ); $leftwidth = array_map('strlen', $leftrow); $maxwidth = max($leftwidth) + 2; array_walk($leftrow, array($this, '_pgpPrettyKeyFormatter'), $maxwidth); foreach ($packet_info['signature'] as $uid_idx => $val) { if ($uid_idx == '_SIGNATURE') { continue; } $key_info = $this->pgpPacketSignatureByUidIndex($pgpdata, $uid_idx); $keyid = empty($key_info['keyid']) ? null : $this->getKeyIDString($key_info['keyid']); $fingerprint = isset($fingerprints[$keyid]) ? $fingerprints[$keyid] : null; $sig_key = 'sig_' . $key_info['keyid']; $msg .= $leftrow[0] . (isset($key_info['name']) ? stripcslashes($key_info['name']) : '') . "\n" . $leftrow[1] . (($key_info['key_type'] == 'public_key') ? Horde_Crypt_Translation::t("Public Key") : Horde_Crypt_Translation::t("Private Key")) . "\n" . $leftrow[2] . strftime("%D", $val[$sig_key]['created']) . "\n" . $leftrow[3] . (empty($val[$sig_key]['expires']) ? '[' . Horde_Crypt_Translation::t("Never") . ']' : strftime("%D", $val[$sig_key]['expires'])) . "\n" . $leftrow[4] . $key_info['key_size'] . " Bytes\n" . $leftrow[5] . (empty($key_info['comment']) ? '[' . Horde_Crypt_Translation::t("None") . ']' : $key_info['comment']) . "\n" . $leftrow[6] . (empty($key_info['email']) ? '[' . Horde_Crypt_Translation::t("None") . ']' : $key_info['email']) . "\n" . $leftrow[7] . (empty($key_info['micalg']) ? '[' . Horde_Crypt_Translation::t("Unknown") . ']' : $key_info['micalg']) . "\n" . $leftrow[8] . (empty($keyid) ? '[' . Horde_Crypt_Translation::t("Unknown") . ']' : $keyid) . "\n" . $leftrow[9] . (empty($fingerprint) ? '[' . Horde_Crypt_Translation::t("Unknown") . ']' : $fingerprint) . "\n\n"; } } return $msg; } /** * TODO */ protected function _pgpPrettyKeyFormatter(&$s, $k, $m) { $s .= ':' . str_repeat(' ', $m - Horde_String::length($s)); } /** * TODO * * @since 2.4.0 */ public function getKeyIDString($keyid) { /* Get the 8 character key ID string. */ if (strpos($keyid, '0x') === 0) { $keyid = substr($keyid, 2); } if (strlen($keyid) > 8) { $keyid = substr($keyid, -8); } return '0x' . $keyid; } /** * Returns only information on the first ID that matches the email address * input. * * @param string $pgpdata The PGP data block. * @param string $email An e-mail address. * * @return array An array with information on the PGP data block. If an * element is not present in the data block, it will * likewise not be set in the array. *
* Array Fields: * ------------- * key_created => Key creation - UNIX timestamp * key_expires => Key expiration - UNIX timestamp (0 = never expires) * key_size => Size of the key in bits * key_type => The key type (public_key or secret_key) * name => Full Name * comment => Comment * email => E-mail Address * keyid => 16-bit hex value * created => Signature creation - UNIX timestamp * micalg => The hash used to create the signature ** @throws Horde_Crypt_Exception */ public function pgpPacketSignature($pgpdata, $email) { $data = $this->pgpPacketInformation($pgpdata); $return_array = array(); /* Check that [signature] key exists. */ if (!isset($data['signature'])) { return $return_array; } /* Store the signature information now. */ if (($email == '_SIGNATURE') && isset($data['signature']['_SIGNATURE'])) { foreach ($data['signature'][$email] as $key => $value) { $return_array[$key] = $value; } } else { $uid_idx = 1; while (isset($data['signature']['id' . $uid_idx])) { if ($data['signature']['id' . $uid_idx]['email'] == $email) { foreach ($data['signature']['id' . $uid_idx] as $key => $val) { $return_array[$key] = $val; } break; } $uid_idx++; } } return $this->_pgpPacketSignature($data, $return_array); } /** * Returns information on a PGP signature embedded in PGP data. Similar * to pgpPacketSignature(), but returns information by unique User ID * Index (format id{n} where n is an integer of 1 or greater). * * @param string $pgpdata See pgpPacketSignature(). * @param string $uid_idx The UID index. * * @return array See pgpPacketSignature(). * @throws Horde_Crypt_Exception */ public function pgpPacketSignatureByUidIndex($pgpdata, $uid_idx) { $data = $this->pgpPacketInformation($pgpdata); return isset($data['signature'][$uid_idx]) ? $this->_pgpPacketSignature($data, $data['signature'][$uid_idx]) : array(); } /** * Adds some data to the pgpPacketSignature*() function array. * * @param array $data See pgpPacketSignature(). * @param array $retarray The return array. * * @return array The return array. */ protected function _pgpPacketSignature($data, $retarray) { /* If empty, return now. */ if (empty($retarray)) { return $retarray; } $key_type = null; /* Store any public/private key information. */ if (isset($data['public_key'])) { $key_type = 'public_key'; } elseif (isset($data['secret_key'])) { $key_type = 'secret_key'; } if ($key_type) { $retarray['key_type'] = $key_type; if (isset($data[$key_type]['created'])) { $retarray['key_created'] = $data[$key_type]['created']; } if (isset($data[$key_type]['expires'])) { $retarray['key_expires'] = $data[$key_type]['expires']; } if (isset($data[$key_type]['size'])) { $retarray['key_size'] = $data[$key_type]['size']; } } return $retarray; } /** * Returns the key ID of the key used to sign a block of PGP data. * * @param string $text The PGP signed text block. * * @return string The key ID of the key used to sign $text. * @throws Horde_Crypt_Exception */ public function getSignersKeyID($text) { $keyid = null; $input = $this->_createTempFile('horde-pgp'); file_put_contents($input, $text); $cmdline = array( '--verify', $input ); $result = $this->_callGpg($cmdline, 'r', null, true, true); if (preg_match('/gpg:\sSignature\smade.*ID\s+([A-F0-9]{8})\s+/', $result->stderr, $matches)) { $keyid = $matches[1]; } return $keyid; } /** * Verify a passphrase for a given public/private keypair. * * @param string $public_key The user's PGP public key. * @param string $private_key The user's PGP private key. * @param string $passphrase The user's passphrase. * * @return boolean Returns true on valid passphrase, false on invalid * passphrase. * @throws Horde_Crypt_Exception */ public function verifyPassphrase($public_key, $private_key, $passphrase) { /* Get e-mail address of public key. */ $key_info = $this->pgpPacketInformation($public_key); if (!isset($key_info['signature']['id1']['email'])) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not determine the recipient's e-mail address.")); } /* Encrypt a test message. */ try { $result = $this->encrypt('Test', array('type' => 'message', 'pubkey' => $public_key, 'recips' => array($key_info['signature']['id1']['email'] => $public_key))); } catch (Horde_Crypt_Exception $e) { return false; } /* Try to decrypt the message. */ try { $this->decrypt($result, array('type' => 'message', 'pubkey' => $public_key, 'privkey' => $private_key, 'passphrase' => $passphrase)); } catch (Horde_Crypt_Exception $e) { return false; } return true; } /** * Parses a message into text and PGP components. * * @deprecated Use Horde_Crypt_Pgp_Parse instead. * * @param mixed $text Either the text to parse or a Horde_Stream object * (@since 2.3.0). * * @return array An array with the parsed text, returned in blocks of * text corresponding to their actual order. Keys: *
* - data: (array) The data for each section. Each line has been * stripped of EOL characters. * - type: (integer) The type of data contained in block. Valid types * are the class ARMOR_* constants. **/ public function parsePGPData($text) { $parse = new Horde_Crypt_Pgp_Parse(); return $parse->parse($text); } /** * Returns a PGP public key from a public keyserver. * * @deprecated Use Horde_Crypt_Pgp_Keyserver instead. * * @param string $keyid The key ID of the PGP key. * @param string $server The keyserver to use. * @param float $timeout The keyserver timeout. * @param string $address The email address of the PGP key. * * @return string The PGP public key. * @throws Horde_Crypt_Exception */ public function getPublicKeyserver($keyid, $server = self::KEYSERVER_PUBLIC, $timeout = self::KEYSERVER_TIMEOUT, $address = null) { $keyserver = $this->_getKeyserverOb($server); if (empty($keyid) && !empty($address)) { $keyid = $keyserver->getKeyID($address); } return $keyserver->get($keyid); } /** * Sends a PGP public key to a public keyserver. * * @param string $pubkey The PGP public key * @param string $server The keyserver to use. * @param float $timeout The keyserver timeout. * * @throws Horde_Crypt_Exception */ public function putPublicKeyserver($pubkey, $server = self::KEYSERVER_PUBLIC, $timeout = self::KEYSERVER_TIMEOUT) { return $this->_getKeyserverOb($server)->put($pubkey); } /** * Returns the first matching key ID for an email address from a * public keyserver. * * @param string $address The email address of the PGP key. * @param string $server The keyserver to use. * @param float $timeout The keyserver timeout. * * @return string The PGP key ID. * @throws Horde_Crypt_Exception */ public function getKeyID($address, $server = self::KEYSERVER_PUBLIC, $timeout = self::KEYSERVER_TIMEOUT) { return $this->_getKeyserverOb($server)->getKeyId($address); } /** * @deprecated * @internal */ protected function _getKeyserverOb($server) { $params = array( 'keyserver' => $server, 'http' => new Horde_Http_Client() ); if (!empty($this->_params['proxy_host'])) { $params['http']->{'request.proxyServer'} = $this->_params['proxy_host']; if (isset($this->_params['proxy_port'])) { $params['http']->{'request.proxyPort'} = $this->_params['proxy_port']; } } return new Horde_Crypt_Pgp_Keyserver($this, $params); } /** * Get the fingerprints from a key block. * * @param string $pgpdata The PGP data block. * * @return array The fingerprints in $pgpdata indexed by key id. * @throws Horde_Crypt_Exception */ public function getFingerprintsFromKey($pgpdata) { $fingerprints = array(); /* Store the key in a temporary keyring. */ $keyring = $this->_putInKeyring($pgpdata); /* Options for the GPG binary. */ $cmdline = array( '--fingerprint', $keyring, ); $result = $this->_callGpg($cmdline, 'r'); if (!$result || !$result->stdout) { return $fingerprints; } /* Parse fingerprints and key ids from output. */ $lines = explode("\n", $result->stdout); $keyid = null; foreach ($lines as $line) { if (preg_match('/pub\s+\w+\/(\w{8})/', $line, $matches)) { $keyid = '0x' . $matches[1]; } elseif ($keyid && preg_match('/^\s+[\s\w]+=\s*([\w\s]+)$/m', $line, $matches)) { $fingerprints[$keyid] = trim($matches[1]); $keyid = null; } } return $fingerprints; } /** * Encrypts text using PGP. * * @param string $text The text to be PGP encrypted. * @param array $params The parameters needed for encryption. * See the individual _encrypt*() functions for the * parameter requirements. * * @return string The encrypted message. * @throws Horde_Crypt_Exception */ public function encrypt($text, $params = array()) { if (isset($params['type'])) { if ($params['type'] === 'message') { return $this->_encryptMessage($text, $params); } elseif ($params['type'] === 'signature') { return $this->_encryptSignature($text, $params); } } } /** * Decrypts text using PGP. * * @param string $text The text to be PGP decrypted. * @param array $params The parameters needed for decryption. * See the individual _decrypt*() functions for the * parameter requirements. * * @return stdClass An object with the following properties: *
* 'message' - (string) The signature result text. * 'result' - (boolean) The result of the signature test. ** @throws Horde_Crypt_Exception */ public function decrypt($text, $params = array()) { if (isset($params['type'])) { if ($params['type'] === 'message') { return $this->_decryptMessage($text, $params); } elseif (($params['type'] === 'signature') || ($params['type'] === 'detached-signature')) { return $this->_decryptSignature($text, $params); } } } /** * Returns whether a text has been encrypted symmetrically. * * @param string $text The PGP encrypted text. * * @return boolean True if the text is symmetricallly encrypted. * @throws Horde_Crypt_Exception */ public function encryptedSymmetrically($text) { $cmdline = array( '--decrypt', '--batch', '--passphrase ""' ); $result = $this->_callGpg($cmdline, 'w', $text, true, true, true); return strpos($result->stderr, 'gpg: encrypted with 1 passphrase') !== false; } /** * Creates a temporary gpg keyring. * * @param string $type The type of key to analyze. Either 'public' * (Default) or 'private' * * @return string Command line keystring option to use with gpg program. */ protected function _createKeyring($type = 'public') { $type = Horde_String::lower($type); if ($type === 'public') { if (empty($this->_publicKeyring)) { $this->_publicKeyring = $this->_createTempFile('horde-pgp'); } return '--keyring ' . $this->_publicKeyring; } elseif ($type === 'private') { if (empty($this->_privateKeyring)) { $this->_privateKeyring = $this->_createTempFile('horde-pgp'); } return '--secret-keyring ' . $this->_privateKeyring; } } /** * Adds PGP keys to the keyring. * * @param mixed $keys A single key or an array of key(s) to add to the * keyring. * @param string $type The type of key(s) to add. Either 'public' * (Default) or 'private' * * @return string Command line keystring option to use with gpg program. * @throws Horde_Crypt_Exception */ protected function _putInKeyring($keys = array(), $type = 'public') { $type = Horde_String::lower($type); if (!is_array($keys)) { $keys = array($keys); } /* Create the keyrings if they don't already exist. */ $keyring = $this->_createKeyring($type); /* Store the key(s) in the keyring. */ $cmdline = array( '--allow-secret-key-import', '--fast-import', $keyring ); $this->_callGpg($cmdline, 'w', array_values($keys)); return $keyring; } /** * Encrypts a message in PGP format using a public key. * * @param string $text The text to be encrypted. * @param array $params The parameters needed for encryption. *
* Parameters: * =========== * 'type' => 'message' (REQUIRED) * 'symmetric' => Whether to use symmetric instead of asymmetric * encryption (defaults to false) * 'recips' => An array with the e-mail address of the recipient as * the key and that person's public key as the value. * (REQUIRED if 'symmetric' is false) * 'passphrase' => The passphrase for the symmetric encryption (REQUIRED if * 'symmetric' is true) ** * @return string The encrypted message. * @throws Horde_Crypt_Exception */ protected function _encryptMessage($text, $params) { /* Create temp files for input. */ $input = $this->_createTempFile('horde-pgp'); file_put_contents($input, $text); /* Build command line. */ $cmdline = array( '--armor', '--batch', '--always-trust' ); if (empty($params['symmetric'])) { /* Store public key in temporary keyring. */ $keyring = $this->_putInKeyring(array_values($params['recips'])); $cmdline[] = $keyring; $cmdline[] = '--encrypt'; foreach (array_keys($params['recips']) as $val) { $cmdline[] = '--recipient ' . $val; } } else { $cmdline[] = '--symmetric'; $cmdline[] = '--passphrase-fd 0'; } $cmdline[] = $input; /* Encrypt the document. */ $result = $this->_callGpg($cmdline, 'w', empty($params['symmetric']) ? null : $params['passphrase'], true, true); if (empty($result->output)) { $error = preg_replace('/\n.*/', '', $result->stderr); throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not PGP encrypt message: ") . $error); } return $result->output; } /** * Signs a message in PGP format using a private key. * * @param string $text The text to be signed. * @param array $params The parameters needed for signing. *
* Parameters: * =========== * 'type' => 'signature' (REQUIRED) * 'pubkey' => PGP public key. (REQUIRED) * 'privkey' => PGP private key. (REQUIRED) * 'passphrase' => Passphrase for PGP Key. (REQUIRED) * 'sigtype' => Determine the signature type to use. (Optional) * 'cleartext' -- Make a clear text signature * 'detach' -- Make a detached signature (DEFAULT) ** * @return string The signed message. * @throws Horde_Crypt_Exception */ protected function _encryptSignature($text, $params) { /* Check for required parameters. */ if (!isset($params['pubkey']) || !isset($params['privkey']) || !isset($params['passphrase'])) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("A public PGP key, private PGP key, and passphrase are required to sign a message.")); } /* Create temp files for input. */ $input = $this->_createTempFile('horde-pgp'); /* Encryption requires both keyrings. */ $pub_keyring = $this->_putInKeyring(array($params['pubkey'])); $sec_keyring = $this->_putInKeyring(array($params['privkey']), 'private'); /* Store message in temporary file. */ file_put_contents($input, $text); /* Determine the signature type to use. */ $cmdline = array(); if (isset($params['sigtype']) && $params['sigtype'] == 'cleartext') { $sign_type = '--clearsign'; } else { $sign_type = '--detach-sign'; } /* Additional GPG options. */ $cmdline += array( '--armor', '--batch', '--passphrase-fd 0', $sec_keyring, $pub_keyring, $sign_type, $input ); /* Sign the document. */ $result = $this->_callGpg($cmdline, 'w', $params['passphrase'], true, true); if (empty($result->output)) { $error = preg_replace('/\n.*/', '', $result->stderr); throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not PGP sign message: ") . $error); } return $result->output; } /** * Decrypts an PGP encrypted message using a private/public keypair and a * passhprase. * * @param string $text The text to be decrypted. * @param array $params The parameters needed for decryption. *
* Parameters: * =========== * 'type' => 'message' (REQUIRED) * 'pubkey' => PGP public key. (REQUIRED for asymmetric encryption) * 'privkey' => PGP private key. (REQUIRED for asymmetric encryption) * 'passphrase' => Passphrase for PGP Key. (REQUIRED) ** * @return stdClass An object with the following properties: *
* 'message' - (string) The signature result text. * 'result' - (boolean) The result of the signature test. ** @throws Horde_Crypt_Exception */ protected function _decryptMessage($text, $params) { /* Check for required parameters. */ if (!isset($params['passphrase']) && empty($params['no_passphrase'])) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("A passphrase is required to decrypt a message.")); } /* Create temp files. */ $input = $this->_createTempFile('horde-pgp'); /* Store message in file. */ file_put_contents($input, $text); /* Build command line. */ $cmdline = array( '--always-trust', '--armor', '--batch' ); if (empty($params['no_passphrase'])) { $cmdline[] = '--passphrase-fd 0'; } if (!empty($params['pubkey']) && !empty($params['privkey'])) { /* Decryption requires both keyrings. */ $pub_keyring = $this->_putInKeyring(array($params['pubkey'])); $sec_keyring = $this->_putInKeyring(array($params['privkey']), 'private'); $cmdline[] = $sec_keyring; $cmdline[] = $pub_keyring; } $cmdline[] = '--decrypt'; $cmdline[] = $input; /* Decrypt the document now. */ $language = getenv('LC_MESSAGES'); putenv('LC_MESSAGES=C'); if (empty($params['no_passphrase'])) { $result = $this->_callGpg($cmdline, 'w', $params['passphrase'], true, true); } else { $result = $this->_callGpg($cmdline, 'r', null, true, true); } putenv('LC_MESSAGES=' . $language); if (empty($result->output)) { $error = preg_replace('/\n.*/', '', $result->stderr); throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not decrypt PGP data: ") . $error); } /* Create the return object. */ return $this->_checkSignatureResult($result->stderr, $result->output); } /** * Decrypts an PGP signed message using a public key. * * @param string $text The text to be verified. * @param array $params The parameters needed for verification. *
* Parameters: * =========== * 'type' => 'signature' or 'detached-signature' (REQUIRED) * 'pubkey' => PGP public key. (REQUIRED) * 'signature' => PGP signature block. (REQUIRED for detached signature) * 'charset' => charset of the message body (OPTIONAL) ** * @return stdClass An object with the following properties: *
* 'message' - (string) The signature result text. * 'result' - (boolean) The result of the signature test. ** @throws Horde_Crypt_Exception */ protected function _decryptSignature($text, $params) { /* Check for required parameters. */ if (!isset($params['pubkey'])) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("A public PGP key is required to verify a signed message.")); } if (($params['type'] === 'detached-signature') && !isset($params['signature'])) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("The detached PGP signature block is required to verify the signed message.")); } /* Create temp files for input. */ $input = $this->_createTempFile('horde-pgp'); /* Store public key in temporary keyring. */ $keyring = $this->_putInKeyring($params['pubkey']); /* Store the message in a temporary file. */ file_put_contents($input, $text); /* Options for the GPG binary. */ $cmdline = array( '--armor', '--always-trust', '--batch', '--charset ' . (isset($params['charset']) ? $params['charset'] : 'UTF-8'), $keyring, '--verify' ); /* Extra stuff to do if we are using a detached signature. */ if ($params['type'] === 'detached-signature') { $sigfile = $this->_createTempFile('horde-pgp'); $cmdline[] = $sigfile . ' ' . $input; file_put_contents($sigfile, $params['signature']); } else { $cmdline[] = $input; } /* Verify the signature. We need to catch standard error output, * since this is where the signature information is sent. */ $language = getenv('LC_MESSAGES'); putenv('LC_MESSAGES=C'); $result = $this->_callGpg($cmdline, 'r', null, true, true); putenv('LC_MESSAGES=' . $language); return $this->_checkSignatureResult($result->stderr, $result->stderr); } /** * Checks signature result from the GnuPG binary. * * @param string $result The signature result. * @param string $message The decrypted message data. * * @return stdClass An object with the following properties: * - message: (string) The signature result text. * - result: (string) The result of the signature test. * * @throws Horde_Crypt_Exception */ protected function _checkSignatureResult($result, $message = null) { /* Good signature: * gpg: Good signature from "blah blah blah (Comment)" * Bad signature: * gpg: BAD signature from "blah blah blah (Comment)" */ if (strpos($result, 'gpg: BAD signature') !== false) { throw new Horde_Crypt_Exception($result); } $ob = new stdClass; $ob->message = $message; $ob->result = $result; return $ob; } /** * Signs a MIME part using PGP. * * @param Horde_Mime_Part $mime_part The object to sign. * @param array $params The parameters required for signing. * @see _encryptSignature(). * * @return mixed A Horde_Mime_Part object that is signed according to RFC * 3156. * @throws Horde_Crypt_Exception */ public function signMIMEPart($mime_part, $params = array()) { $params = array_merge($params, array('type' => 'signature', 'sigtype' => 'detach')); /* RFC 3156 Requirements for a PGP signed message: * + Content-Type params 'micalg' & 'protocol' are REQUIRED. * + The digitally signed message MUST be constrained to 7 bits. * + The MIME headers MUST be a part of the signed data. */ $msg_sign = $this->encrypt($mime_part->toString(array('headers' => true, 'canonical' => true, 'encode' => Horde_Mime_Part::ENCODE_7BIT)), $params); /* Add the PGP signature. */ $pgp_sign = new Horde_Mime_Part(); $pgp_sign->setType('application/pgp-signature'); $pgp_sign->setHeaderCharset('UTF-8'); $pgp_sign->setDisposition('inline'); $pgp_sign->setDescription(Horde_Crypt_Translation::t("PGP Digital Signature")); $pgp_sign->setContents($msg_sign, array('encoding' => '7bit')); /* Get the algorithim information from the signature. Since we are * analyzing a signature packet, we need to use the special keyword * '_SIGNATURE' - see Horde_Crypt_Pgp. */ $sig_info = $this->pgpPacketSignature($msg_sign, '_SIGNATURE'); /* Setup the multipart MIME Part. */ $part = new Horde_Mime_Part(); $part->setType('multipart/signed'); $part->setContents("This message is in MIME format and has been PGP signed.\n"); $part->addPart($mime_part); $part->addPart($pgp_sign); $part->setContentTypeParameter('protocol', 'application/pgp-signature'); $part->setContentTypeParameter('micalg', $sig_info['micalg']); return $part; } /** * Encrypts a MIME part using PGP. * * @param Horde_Mime_Part $mime_part The object to encrypt. * @param array $params The parameters required for * encryption. * @see _encryptMessage(). * * @return mixed A Horde_Mime_Part object that is encrypted according to * RFC 3156. * @throws Horde_Crypt_Exception */ public function encryptMIMEPart($mime_part, $params = array()) { $params = array_merge($params, array('type' => 'message')); $signenc_body = $mime_part->toString(array('headers' => true, 'canonical' => true)); $message_encrypt = $this->encrypt($signenc_body, $params); /* Set up MIME Structure according to RFC 3156. */ $part = new Horde_Mime_Part(); $part->setType('multipart/encrypted'); $part->setHeaderCharset('UTF-8'); $part->setContentTypeParameter('protocol', 'application/pgp-encrypted'); $part->setDescription(Horde_Crypt_Translation::t("PGP Encrypted Data")); $part->setContents("This message is in MIME format and has been PGP encrypted.\n"); $part1 = new Horde_Mime_Part(); $part1->setType('application/pgp-encrypted'); $part1->setCharset(null); $part1->setContents("Version: 1\n", array('encoding' => '7bit')); $part->addPart($part1); $part2 = new Horde_Mime_Part(); $part2->setType('application/octet-stream'); $part2->setCharset(null); $part2->setContents($message_encrypt, array('encoding' => '7bit')); $part2->setDisposition('inline'); $part->addPart($part2); return $part; } /** * Signs and encrypts a MIME part using PGP. * * @param Horde_Mime_Part $mime_part The object to sign and encrypt. * @param array $sign_params The parameters required for * signing. @see _encryptSignature(). * @param array $encrypt_params The parameters required for * encryption. @see _encryptMessage(). * * @return mixed A Horde_Mime_Part object that is signed and encrypted * according to RFC 3156. * @throws Horde_Crypt_Exception */ public function signAndEncryptMIMEPart($mime_part, $sign_params = array(), $encrypt_params = array()) { /* RFC 3156 requires that the entire signed message be encrypted. We * need to explicitly call using Horde_Crypt_Pgp:: because we don't * know whether a subclass has extended these methods. */ $part = $this->signMIMEPart($mime_part, $sign_params); $part = $this->encryptMIMEPart($part, $encrypt_params); $part->setContents("This message is in MIME format and has been PGP signed and encrypted.\n"); $part->setCharset($this->_params['email_charset']); $part->setDescription(Horde_String::convertCharset(Horde_Crypt_Translation::t("PGP Signed/Encrypted Data"), 'UTF-8', $this->_params['email_charset'])); return $part; } /** * Generates a Horde_Mime_Part object, in accordance with RFC 3156, that * contains a public key. * * @param string $key The public key. * * @return Horde_Mime_Part An object that contains the public key. */ public function publicKeyMIMEPart($key) { $part = new Horde_Mime_Part(); $part->setType('application/pgp-keys'); $part->setHeaderCharset('UTF-8'); $part->setDescription(Horde_Crypt_Translation::t("PGP Public Key")); $part->setContents($key, array('encoding' => '7bit')); return $part; } /** * Function that handles interfacing with the GnuPG binary. * * @param array $options Options and commands to pass to GnuPG. * @param string $mode 'r' to read from stdout, 'w' to write to * stdin. * @param array $input Input to write to stdin. * @param boolean $output Collect and store output in object returned? * @param boolean $stderr Collect and store stderr in object returned? * @param boolean $verbose Run GnuPG with verbose flag? * * @return stdClass Class with members output, stderr, and stdout. * @throws Horde_Crypt_Exception */ protected function _callGpg($options, $mode, $input = array(), $output = false, $stderr = false, $verbose = false) { $data = new stdClass; $data->output = null; $data->stderr = null; $data->stdout = null; /* Verbose output? */ if (!$verbose) { array_unshift($options, '--quiet'); } /* Create temp files for output. */ if ($output) { $output_file = $this->_createTempFile('horde-pgp', false); array_unshift($options, '--output ' . $output_file); /* Do we need standard error output? */ if ($stderr) { $stderr_file = $this->_createTempFile('horde-pgp', false); $options[] = '2> ' . $stderr_file; } } /* Silence errors if not requested. */ if (!$output || !$stderr) { $options[] = '2> /dev/null'; } /* Build the command line string now. */ $cmdline = implode(' ', array_merge($this->_gnupg, $options)); if ($mode == 'w') { if ($fp = popen($cmdline, 'w')) { $win32 = !strncasecmp(PHP_OS, 'WIN', 3); if (!is_array($input)) { $input = array($input); } foreach ($input as $line) { if ($win32 && (strpos($line, "\x0d\x0a") !== false)) { $chunks = explode("\x0d\x0a", $line); foreach ($chunks as $chunk) { fputs($fp, $chunk . "\n"); } } else { fputs($fp, $line . "\n"); } } } else { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Error while talking to pgp binary.")); } } elseif ($mode == 'r') { if ($fp = popen($cmdline, 'r')) { while (!feof($fp)) { $data->stdout .= fgets($fp, 1024); } } else { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Error while talking to pgp binary.")); } } pclose($fp); if ($output) { $data->output = file_get_contents($output_file); unlink($output_file); if ($stderr) { $data->stderr = file_get_contents($stderr_file); unlink($stderr_file); } } return $data; } /** * Generates a public key from a private key. * * @param string $data Armor text of private key. * * @return string Armor text of public key, or null if it could not be * generated. */ public function getPublicKeyFromPrivateKey($data) { $this->_putInKeyring(array($data), 'private'); $fingerprints = $this->getFingerprintsFromKey($data); reset($fingerprints); $cmdline = array( '--armor', '--export', key($fingerprints) ); $result = $this->_callGpg($cmdline, 'r', array(), true, true); return empty($result->output) ? null : $result->output; } /** * @deprecated */ public function generateRevocation($key, $email, $passphrase) { throw new Horde_Crypt_Exception('Not supported'); } } Horde_Crypt-2.4.0/lib/Horde/Crypt/Smime.php 0000664 0001750 0001750 00000072444 12242643672 016561 0 ustar jan jan * @author Michael Slusarz
* cert - (string) The certificate of the signer stored in the message (in * PEM format). * email - (string) The email of the signing person. * msg - (string) Status string. * verify - (boolean) True if certificate was verified. ** @throws Horde_Crypt_Exception */ public function verify($text, $certs) { /* Check for availability of OpenSSL PHP extension. */ $this->checkForOpenSSL(); /* Create temp files for input/output. */ $input = $this->_createTempFile('horde-smime'); $output = $this->_createTempFile('horde-smime'); /* Write text to file */ file_put_contents($input, $text); unset($text); $root_certs = array(); if (!is_array($certs)) { $certs = array($certs); } foreach ($certs as $file) { if (file_exists($file)) { $root_certs[] = $file; } } $ob = new stdClass; if (!empty($root_certs) && (openssl_pkcs7_verify($input, 0, $output, $root_certs) === true)) { /* Message verified */ $ob->msg = Horde_Crypt_Translation::t("Message verified successfully."); $ob->verify = true; } else { /* Try again without verfying the signer's cert */ $result = openssl_pkcs7_verify($input, PKCS7_NOVERIFY, $output); if ($result === -1) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Verification failed - an unknown error has occurred.")); } elseif ($result === false) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Verification failed - this message may have been tampered with.")); } $ob->msg = Horde_Crypt_Translation::t("Message verified successfully but the signer's certificate could not be verified."); $ob->verify = false; } $ob->cert = file_get_contents($output); $ob->email = $this->getEmailFromKey($ob->cert); return $ob; } /** * Extract the contents from signed S/MIME data. * * @param string $data The signed S/MIME data. * @param string $sslpath The path to the OpenSSL binary. * * @return string The contents embedded in the signed data. * @throws Horde_Crypt_Exception */ public function extractSignedContents($data, $sslpath) { /* Check for availability of OpenSSL PHP extension. */ $this->checkForOpenSSL(); /* Create temp files for input/output. */ $input = $this->_createTempFile('horde-smime'); $output = $this->_createTempFile('horde-smime'); /* Write text to file. */ file_put_contents($input, $data); unset($data); exec($sslpath . ' smime -verify -noverify -nochain -in ' . $input . ' -out ' . $output); $ret = file_get_contents($output); if ($ret) { return $ret; } throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("OpenSSL error: Could not extract data from signed S/MIME part.")); } /** * Sign a MIME part using S/MIME. This produces S/MIME Version 3.2 * compatible data (see RFC 5751 [3.4]). * * @param Horde_Mime_Part $mime_part The object to sign. * @param array $params The parameters required for signing. * * @return Horde_Mime_Part A signed MIME part object. * @throws Horde_Crypt_Exception */ public function signMIMEPart($mime_part, $params) { /* Sign the part as a message */ $message = $this->encrypt($mime_part->toString(array('headers' => true, 'canonical' => true)), $params); /* Break the result into its components */ $mime_message = Horde_Mime_Part::parseMessage($message, array('forcemime' => true)); $smime_sign = $mime_message->getPart('2'); $smime_sign->setDescription(Horde_Crypt_Translation::t("S/MIME Signature")); $smime_sign->setTransferEncoding('base64', array('send' => true)); $smime_part = new Horde_Mime_Part(); $smime_part->setType('multipart/signed'); $smime_part->setContents("This is a cryptographically signed message in MIME format.\n"); $smime_part->setContentTypeParameter('protocol', 'application/pkcs7-signature'); // Per RFC 5751 [3.4.3.2], 'sha1' has been deprecated for 'sha-1'. $smime_part->setContentTypeParameter('micalg', 'sha-1'); $smime_part->addPart($mime_part); $smime_part->addPart($smime_sign); return $smime_part; } /** * Encrypt a MIME part using S/MIME. This produces S/MIME Version 3.2 * compatible data (see RFC 5751 [3.3]). * * @param Horde_Mime_Part $mime_part The object to encrypt. * @param array $params The parameters required for * encryption. * * @return Horde_Mime_Part An encrypted MIME part object. * @throws Horde_Crypt_Exception */ public function encryptMIMEPart($mime_part, $params = array()) { /* Sign the part as a message */ $message = $this->encrypt($mime_part->toString(array('headers' => true, 'canonical' => true)), $params); $msg = new Horde_Mime_Part(); $msg->setCharset($this->_params['email_charset']); $msg->setHeaderCharset('UTF-8'); $msg->setDescription(Horde_Crypt_Translation::t("S/MIME Encrypted Message")); $msg->setDisposition('inline'); $msg->setType('application/pkcs7-mime'); $msg->setContentTypeParameter('smime-type', 'enveloped-data'); $msg->setContents(substr($message, strpos($message, "\n\n") + 2), array('encoding' => 'base64')); return $msg; } /** * Encrypt a message in S/MIME format using a public key. * * @param string $text The text to be encrypted. * @param array $params The parameters needed for encryption. *
* Parameters: * =========== * 'type' => 'message' (REQUIRED) * 'pubkey' => public key (REQUIRED) ** * @return string The encrypted message. * @throws Horde_Crypt_Exception */ protected function _encryptMessage($text, $params) { /* Check for required parameters. */ if (!isset($params['pubkey'])) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("A public S/MIME key is required to encrypt a message.")); } /* Create temp files for input/output. */ $input = $this->_createTempFile('horde-smime'); $output = $this->_createTempFile('horde-smime'); /* Store message in file. */ file_put_contents($input, $text); unset($text); /* Encrypt the document. */ $ciphers = array( OPENSSL_CIPHER_3DES, OPENSSL_CIPHER_DES, OPENSSL_CIPHER_RC2_128, OPENSSL_CIPHER_RC2_64, OPENSSL_CIPHER_RC2_40 ); foreach ($ciphers as $val) { if (openssl_pkcs7_encrypt($input, $output, $params['pubkey'], array(), 0, $val)) { $result = file_get_contents($output); if (!empty($result)) { return $this->_fixContentType($result, 'encrypt'); } } } throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not S/MIME encrypt message.")); } /** * Sign a message in S/MIME format using a private key. * * @param string $text The text to be signed. * @param array $params The parameters needed for signing. *
* Parameters: * =========== * 'certs' => Additional signing certs (Optional) * 'passphrase' => Passphrase for key (REQUIRED) * 'privkey' => Private key (REQUIRED) * 'pubkey' => Public key (REQUIRED) * 'sigtype' => Determine the signature type to use. (Optional) * 'cleartext' -- Make a clear text signature * 'detach' -- Make a detached signature (DEFAULT) * 'type' => 'signature' (REQUIRED) ** * @return string The signed message. * @throws Horde_Crypt_Exception */ protected function _encryptSignature($text, $params) { /* Check for required parameters. */ if (!isset($params['pubkey']) || !isset($params['privkey']) || !array_key_exists('passphrase', $params)) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("A public S/MIME key, private S/MIME key, and passphrase are required to sign a message.")); } /* Create temp files for input/output/certificates. */ $input = $this->_createTempFile('horde-smime'); $output = $this->_createTempFile('horde-smime'); $certs = $this->_createTempFile('horde-smime'); /* Store message in temporary file. */ file_put_contents($input, $text); unset($text); /* Store additional certs in temporary file. */ if (!empty($params['certs'])) { file_put_contents($certs, $params['certs']); } /* Determine the signature type to use. */ $flags = (isset($params['sigtype']) && ($params['sigtype'] == 'cleartext')) ? PKCS7_TEXT : PKCS7_DETACHED; $privkey = (is_null($params['passphrase'])) ? $params['privkey'] : array($params['privkey'], $params['passphrase']); if (empty($params['certs'])) { $res = openssl_pkcs7_sign($input, $output, $params['pubkey'], $privkey, array(), $flags); } else { $res = openssl_pkcs7_sign($input, $output, $params['pubkey'], $privkey, array(), $flags, $certs); } if (!$res) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not S/MIME sign message.")); } /* Output from openssl_pkcs7_sign may contain both \n and \r\n EOLs. * Canonicalize to \r\n. */ $fp = fopen($output, 'r'); stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol'); stream_filter_append($fp, 'horde_eol'); $data = stream_get_contents($fp); fclose($fp); return $this->_fixContentType($data, 'signature'); } /** * Decrypt an S/MIME encrypted message using a private/public keypair * and a passhprase. * * @param string $text The text to be decrypted. * @param array $params The parameters needed for decryption. *
* Parameters: * =========== * 'type' => 'message' (REQUIRED) * 'pubkey' => public key. (REQUIRED) * 'privkey' => private key. (REQUIRED) * 'passphrase' => Passphrase for Key. (REQUIRED) ** * @return string The decrypted message. * @throws Horde_Crypt_Exception */ protected function _decryptMessage($text, $params) { /* Check for required parameters. */ if (!isset($params['pubkey']) || !isset($params['privkey']) || !array_key_exists('passphrase', $params)) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("A public S/MIME key, private S/MIME key, and passphrase are required to decrypt a message.")); } /* Create temp files for input/output. */ $input = $this->_createTempFile('horde-smime'); $output = $this->_createTempFile('horde-smime'); /* Store message in file. */ file_put_contents($input, $text); unset($text); $privkey = is_null($params['passphrase']) ? $params['privkey'] : array($params['privkey'], $params['passphrase']); if (openssl_pkcs7_decrypt($input, $output, $params['pubkey'], $privkey)) { return file_get_contents($output); } throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Could not decrypt S/MIME data.")); } /** * Sign and Encrypt a MIME part using S/MIME. * * @param Horde_Mime_Part $mime_part The object to sign and encrypt. * @param array $sign_params The parameters required for * signing. @see _encryptSignature(). * @param array $encrypt_params The parameters required for * encryption. * @see _encryptMessage(). * * @return mixed A Horde_Mime_Part object that is signed and encrypted. * @throws Horde_Crypt_Exception */ public function signAndEncryptMIMEPart($mime_part, $sign_params = array(), $encrypt_params = array()) { $part = $this->signMIMEPart($mime_part, $sign_params); return $this->encryptMIMEPart($part, $encrypt_params); } /** * Convert a PEM format certificate to readable HTML version. * * @param string $cert PEM format certificate. * * @return string HTML detailing the certificate. */ public function certToHTML($cert) { $fieldnames = array( /* Common Fields */ 'description' => Horde_Crypt_Translation::t("Description"), 'emailAddress' => Horde_Crypt_Translation::t("Email Address"), 'commonName' => Horde_Crypt_Translation::t("Common Name"), 'organizationName' => Horde_Crypt_Translation::t("Organisation"), 'organizationalUnitName' => Horde_Crypt_Translation::t("Organisational Unit"), 'countryName' => Horde_Crypt_Translation::t("Country"), 'stateOrProvinceName' => Horde_Crypt_Translation::t("State or Province"), 'localityName' => Horde_Crypt_Translation::t("Location"), 'streetAddress' => Horde_Crypt_Translation::t("Street Address"), 'telephoneNumber' => Horde_Crypt_Translation::t("Telephone Number"), 'surname' => Horde_Crypt_Translation::t("Surname"), 'givenName' => Horde_Crypt_Translation::t("Given Name"), /* X590v3 Extensions */ 'exendedtKeyUsage' => Horde_Crypt_Translation::t("X509v3 Extended Key Usage"), 'basicConstraints' => Horde_Crypt_Translation::t("X509v3 Basic Constraints"), 'subjectAltName' => Horde_Crypt_Translation::t("X509v3 Subject Alternative Name"), 'subjectKeyIdentifier' => Horde_Crypt_Translation::t("X509v3 Subject Key Identifier"), 'certificatePolicies' => Horde_Crypt_Translation::t("Certificate Policies"), 'crlDistributionPoints' => Horde_Crypt_Translation::t("CRL Distribution Points"), 'keyUsage' => Horde_Crypt_Translation::t("Key Usage") ); $details = $this->parseCert($cert); $text = '
'; /* Subject (a/k/a Certificate Owner) */ $text .= "" . Horde_Crypt_Translation::t("Certificate Owner") . ":\n"; foreach ($details['subject'] as $key => $value) { $value = htmlspecialchars($this->_implodeValues($value)); $text .= isset($fieldnames[$key]) ? sprintf(" %s: %s\n", htmlspecialchars($fieldnames[$key]), $value) : sprintf(" *%s: %s\n", htmlspecialchars($key), $value); } $text .= "\n"; /* Issuer */ $text .= "" . Horde_Crypt_Translation::t("Issuer") . ":\n"; foreach ($details['issuer'] as $key => $value) { $value = htmlspecialchars($this->_implodeValues($value)); $text .= isset($fieldnames[$key]) ? sprintf(" %s: %s\n", htmlspecialchars($fieldnames[$key]), $value) : sprintf(" *%s: %s\n", htmlspecialchars($key), $value); } $text .= "\n"; /* Dates */ $text .= "" . Horde_Crypt_Translation::t("Validity") . ":\n" . sprintf(" %s: %s\n", Horde_Crypt_Translation::t("Not Before"), strftime("%x %X", $details['validity']['notbefore']->getTimestamp())) . sprintf(" %s: %s\n", Horde_Crypt_Translation::t("Not After"), strftime("%x %X", $details['validity']['notafter']->getTimestamp())) . "\n"; /* X509v3 extensions */ if (!empty($details['extensions'])) { $text .= "" . Horde_Crypt_Translation::t("X509v3 extensions") . ":\n"; foreach ($details['extensions'] as $key => $value) { $value = htmlspecialchars(trim($this->_implodeValues($value, 6))); $text .= isset($fieldnames[$key]) ? sprintf(" %s:\n %s\n", htmlspecialchars($fieldnames[$key]), $value) : sprintf(" *%s:\n %s\n", htmlspecialchars($key), $value); } $text .= "\n"; } /* Certificate Details */ $text .= "" . Horde_Crypt_Translation::t("Certificate Details") . ":\n" . sprintf(" %s: %d\n", Horde_Crypt_Translation::t("Version"), $details['version']) . sprintf(" %s: %d\n", Horde_Crypt_Translation::t("Serial Number"), $details['serialNumber']); return $text . "\n"; } /** * Formats a multi-value cert field. * * @param array|string $value A cert field value. * @param integer $indent The indention level. * * @return string The formatted cert field value(s). */ protected function _implodeValues($value, $indent = 4) { if (is_array($value)) { $value = "\n" . str_repeat(' ', $indent) . implode("\n" . str_repeat(' ', $indent), $value); } return $value; } /** * Extract the contents of a PEM format certificate to an array. * * @param string $cert PEM format certificate. * * @return array All extractable information about the certificate. */ public function parseCert($cert) { $data = openssl_x509_parse($cert, false); if (!$data) { throw new Horde_Crypt_Exception(sprintf(Horde_Crypt_Translation::t("Error parsing S/MIME certficate: %s"), openssl_error_string())); } $details = array( 'extensions' => $data['extensions'], 'issuer' => $data['issuer'], 'serialNumber' => $data['serialNumber'], 'subject' => $data['subject'], 'validity' => array( 'notafter' => new DateTime('@' . $data['validTo_time_t']), 'notbefore' => new DateTime('@' . $data['validFrom_time_t']) ), 'version' => $data['version'] ); // Add additional fields for BC purposes. $details['certificate'] = $details; $bc_changes = array( 'emailAddress' => 'Email', 'commonName' => 'CommonName', 'organizationName' => 'Organisation', 'organizationalUnitName' => 'OrganisationalUnit', 'countryName' => 'Country', 'stateOrProvinceName' => 'StateOrProvince', 'localityName' => 'Location', 'streetAddress' => 'StreetAddress', 'telephoneNumber' => 'TelephoneNumber', 'surname' => 'Surname', 'givenName' => 'GivenName' ); foreach (array('issuer', 'subject') as $val) { foreach (array_keys($details[$val]) as $key) { if (isset($bc_changes[$key])) { $details['certificate'][$val][$bc_changes[$key]] = $details[$val][$key]; unset($details['certificate'][$val][$key]); } } } return $details; } /** * Decrypt an S/MIME signed message using a public key. * * @param string $text The text to be verified. * @param array $params The parameters needed for verification. * * @return string The verification message. * @throws Horde_Crypt_Exception */ protected function _decryptSignature($text, $params) { throw new Horde_Crypt_Exception('_decryptSignature() ' . Horde_Crypt_Translation::t("not yet implemented")); } /** * Check for the presence of the OpenSSL extension to PHP. * * @throws Horde_Crypt_Exception */ public function checkForOpenSSL() { if (!Horde_Util::extensionExists('openssl')) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("The openssl module is required for the Horde_Crypt_Smime:: class.")); } } /** * Extract the email address from a public key. * * @param string $key The public key. * * @return mixed Returns the first email address found, or null if * there are none. */ public function getEmailFromKey($key) { $key_info = openssl_x509_parse($key); if (!is_array($key_info)) { return null; } if (isset($key_info['subject'])) { if (isset($key_info['subject']['Email'])) { return $key_info['subject']['Email']; } elseif (isset($key_info['subject']['emailAddress'])) { return $key_info['subject']['emailAddress']; } } // Check subjectAltName per http://www.ietf.org/rfc/rfc3850.txt if (isset($key_info['extensions']['subjectAltName'])) { $names = preg_split('/\s*,\s*/', $key_info['extensions']['subjectAltName'], -1, PREG_SPLIT_NO_EMPTY); foreach ($names as $name) { if (strpos($name, ':') === false) { continue; } list($kind, $value) = explode(':', $name, 2); if (Horde_String::lower($kind) == 'email') { return $value; } } } return null; } /** * Convert a PKCS 12 encrypted certificate package into a private key, * public key, and any additional keys. * * @param string $pkcs12 The PKCS 12 data. * @param array $params The parameters needed for parsing. *
* Parameters: * =========== * 'sslpath' => The path to the OpenSSL binary. (REQUIRED) * 'password' => The password to use to decrypt the data. (Optional) * 'newpassword' => The password to use to encrypt the private key. * (Optional) ** * @return stdClass An object. * 'private' - The private key in PEM format. * 'public' - The public key in PEM format. * 'certs' - An array of additional certs. * @throws Horde_Crypt_Exception */ public function parsePKCS12Data($pkcs12, $params) { /* Check for availability of OpenSSL PHP extension. */ $this->checkForOpenSSL(); if (!isset($params['sslpath'])) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("No path to the OpenSSL binary provided. The OpenSSL binary is necessary to work with PKCS 12 data.")); } $sslpath = escapeshellcmd($params['sslpath']); /* Create temp files for input/output. */ $input = $this->_createTempFile('horde-smime'); $output = $this->_createTempFile('horde-smime'); $ob = new stdClass; /* Write text to file */ file_put_contents($input, $pkcs12); unset($pkcs12); /* Extract the private key from the file first. */ $cmdline = $sslpath . ' pkcs12 -in ' . $input . ' -out ' . $output . ' -nocerts'; if (isset($params['password'])) { $cmdline .= ' -passin stdin'; if (!empty($params['newpassword'])) { $cmdline .= ' -passout stdin'; } else { $cmdline .= ' -nodes'; } } else { $cmdline .= ' -nodes'; } if ($fd = popen($cmdline, 'w')) { fwrite($fd, $params['password'] . "\n"); if (!empty($params['newpassword'])) { fwrite($fd, $params['newpassword'] . "\n"); } pclose($fd); } else { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Error while talking to smime binary.")); } $ob->private = trim(file_get_contents($output)); if (empty($ob->private)) { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Password incorrect")); } /* Extract the client public key next. */ $cmdline = $sslpath . ' pkcs12 -in ' . $input . ' -out ' . $output . ' -nokeys -clcerts'; if (isset($params['password'])) { $cmdline .= ' -passin stdin'; } if ($fd = popen($cmdline, 'w')) { fwrite($fd, $params['password'] . "\n"); pclose($fd); } else { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Error while talking to smime binary.")); } $ob->public = trim(file_get_contents($output)); /* Extract the CA public key next. */ $cmdline = $sslpath . ' pkcs12 -in ' . $input . ' -out ' . $output . ' -nokeys -cacerts'; if (isset($params['password'])) { $cmdline .= ' -passin stdin'; } if ($fd = popen($cmdline, 'w')) { fwrite($fd, $params['password'] . "\n"); pclose($fd); } else { throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Error while talking to smime binary.")); } $ob->certs = trim(file_get_contents($output)); return $ob; } /** * The Content-Type parameters PHP's openssl_pkcs7_* functions return are * deprecated. Fix these headers to the correct ones (see RFC 2311). * * @param string $text The PKCS7 data. * @param string $type Is this 'message' or 'signature' data? * * @return string The PKCS7 data with the correct Content-Type parameter. */ protected function _fixContentType($text, $type) { if ($type == 'message') { $from = 'application/x-pkcs7-mime'; $to = 'application/pkcs7-mime'; } else { $from = 'application/x-pkcs7-signature'; $to = 'application/pkcs7-signature'; } return str_replace('Content-Type: ' . $from, 'Content-Type: ' . $to, $text); } } Horde_Crypt-2.4.0/lib/Horde/Crypt/Translation.php 0000664 0001750 0001750 00000003356 12242643672 020001 0 ustar jan jan * @category Horde * @package Crypt */ class Horde_Crypt_Translation extends Horde_Translation { /** * Returns the translation of a message. * * @var string $message The string to translate. * * @return string The string translation, or the original string if no * translation exists. */ static public function t($message) { self::$_domain = 'Horde_Crypt'; self::$_directory = '@data_dir@' == '@'.'data_dir'.'@' ? __DIR__ . '/../../../locale' : '@data_dir@/Horde_Crypt/locale'; return parent::t($message); } /** * Returns the plural translation of a message. * * @param string $singular The singular version to translate. * @param string $plural The plural version to translate. * @param integer $number The number that determines singular vs. plural. * * @return string The string translation, or the original string if no * translation exists. */ static public function ngettext($singular, $plural, $number) { self::$_domain = 'Horde_Crypt'; self::$_directory = '@data_dir@' == '@'.'data_dir'.'@' ? __DIR__ . '/../../../locale' : '@data_dir@/Horde_Crypt/locale'; return parent::ngettext($singular, $plural, $number); } } Horde_Crypt-2.4.0/lib/Horde/Crypt.php 0000664 0001750 0001750 00000007663 12242643672 015510 0 ustar jan jan * @category Horde * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Crypt */ class Horde_Crypt { /** * Configuration parameters. * * @var array */ protected $_params = array(); /** * The temporary directory to use. * * @var string */ protected $_tempdir; /** * Attempts to return a concrete Horde_Crypt instance based on $driver. * * @param string $driver Either a driver name, or the full class name to * use (class must extend Horde_Crypt). * @param array $params A hash containing any additional configuration * or parameters a subclass might need. * * @return Horde_Crypt The newly created concrete instance. * @throws Horde_Crypt_Exception */ static public function factory($driver, $params = array()) { /* Return a base Horde_Crypt object if no driver is specified. */ if (empty($driver) || (strcasecmp($driver, 'none') == 0)) { return new Horde_Crypt(); } /* Base drivers (in Crypt/ directory). */ $class = __CLASS__ . '_' . ucfirst(basename($driver)); if (class_exists($class)) { return new $class($params); } /* Explicit class name, */ $class = $driver; if (class_exists($class)) { return new $class($params); } throw new Horde_Crypt_Exception(__CLASS__ . ': Class definition of ' . $driver . ' not found.'); } /** * Constructor. * * @param array $params Configuration parameters: *
* email_charset - (string) The default email charset. * DEFAULT: NONE * temp - (string) [REQUIRED] Location of temporary directory. ** * @throws InvalidArgumentException */ public function __construct(array $params = array()) { if (empty($params['temp'])) { throw new InvalidArgumentException('A temporary directory must be provided.'); } $this->_tempdir = Horde_Util::createTempDir(true, $params['temp']); $this->_params = array_merge(array( 'email_charset' => null, ), $params); } /** * Encrypt the requested data. * This method should be provided by all classes that extend Horde_Crypt. * * @param string $data The data to encrypt. * @param array $params An array of arguments needed to encrypt the data. * * @return array The encrypted data. */ public function encrypt($data, $params = array()) { return $data; } /** * Decrypt the requested data. * This method should be provided by all classes that extend Horde_Crypt. * * @param string $data The data to decrypt. * @param array $params An array of arguments needed to decrypt the data. * * @return array The decrypted data. * @throws Horde_Crypt_Exception */ public function decrypt($data, $params = array()) { return $data; } /** * Create a temporary file that will be deleted at the end of this * process. * * @param string $descrip Description string to use in filename. * @param boolean $delete Delete the file automatically? * * @return string Filename of a temporary file. */ protected function _createTempFile($descrip = 'horde-crypt', $delete = true) { return Horde_Util::getTempFile($descrip, $delete, $this->_tempdir, true); } } Horde_Crypt-2.4.0/locale/ar/LC_MESSAGES/Horde_Crypt.mo 0000664 0001750 0001750 00000000705 12242643672 020262 0 ustar jan jan 4 L ` a f B l Name Never Project-Id-Version: Horde_Crypt Report-Msgid-Bugs-To: dev@lists.horde.org POT-Creation-Date: 2010-10-13 01:27+0200 PO-Revision-Date: 2010-10-13 01:27+0200 Last-Translator: Automatically generated Language-Team: i18n@lists.horde.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit الاسم أبداً Horde_Crypt-2.4.0/locale/ar/LC_MESSAGES/Horde_Crypt.po 0000664 0001750 0001750 00000021375 12242643672 020273 0 ustar jan jan # Arabic translations for Horde_Crypt module. # Copyright 2010-2013 Horde LLC (http://www.horde.org/) # This file is distributed under the same license as the Horde_Crypt module. # Automatically generated, 2010. # msgid "" msgstr "" "Project-Id-Version: Horde_Crypt\n" "Report-Msgid-Bugs-To: dev@lists.horde.org\n" "POT-Creation-Date: 2010-10-13 01:27+0200\n" "PO-Revision-Date: 2010-10-13 01:27+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: i18n@lists.horde.org\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Horde/Crypt/Smime.php:614 #, php-format msgid "%s Fingerprint" msgstr "" #: lib/Horde/Crypt/Pgp.php:1240 msgid "A passphrase is required to decrypt a message." msgstr "" #: lib/Horde/Crypt/Pgp.php:1307 msgid "A public PGP key is required to verify a signed message." msgstr "" #: lib/Horde/Crypt/Pgp.php:1164 msgid "" "A public PGP key, private PGP key, and passphrase are required to sign a " "message." msgstr "" #: lib/Horde/Crypt/Smime.php:311 msgid "A public S/MIME key is required to encrypt a message." msgstr "" #: lib/Horde/Crypt/Smime.php:422 msgid "" "A public S/MIME key, private S/MIME key, and passphrase are required to " "decrypt a message." msgstr "" #: lib/Horde/Crypt/Smime.php:360 msgid "" "A public S/MIME key, private S/MIME key, and passphrase are required to sign " "a message." msgstr "" #: lib/Horde/Crypt/Smime.php:506 msgid "CRL Distribution Points" msgstr "" #: lib/Horde/Crypt/Smime.php:609 msgid "Certificate Details" msgstr "" #: lib/Horde/Crypt/Smime.php:520 msgid "Certificate Owner" msgstr "" #: lib/Horde/Crypt/Smime.php:505 msgid "Certificate Policies" msgstr "" #: lib/Horde/Crypt/Pgp.php:426 #, fuzzy msgid "Comment" msgstr "الأوامر:" #: lib/Horde/Crypt/Smime.php:475 msgid "Common Name" msgstr "" #: lib/Horde/Crypt/Pgp.php:939 #, fuzzy msgid "Connection refused to the public keyserver." msgstr "حصل خطأ خلال الإتصال بمخدم الـ FTP." #: lib/Horde/Crypt/Pgp.php:950 #, php-format msgid "Connection refused to the public keyserver. Reason: %s (%s)" msgstr "" #: lib/Horde/Crypt/Pgp.php:1132 msgid "Could not PGP encrypt message: " msgstr "" #: lib/Horde/Crypt/Pgp.php:1201 msgid "Could not PGP sign message: " msgstr "" #: lib/Horde/Crypt/Smime.php:330 msgid "Could not S/MIME encrypt message." msgstr "" #: lib/Horde/Crypt/Smime.php:391 msgid "Could not S/MIME sign message." msgstr "" #: lib/Horde/Crypt/Pgp.php:1276 #, fuzzy msgid "Could not decrypt PGP data: " msgstr "لا إمكانية لنسخ %s إلى %s" #: lib/Horde/Crypt/Smime.php:440 msgid "Could not decrypt S/MIME data." msgstr "" #: lib/Horde/Crypt/Pgp.php:659 msgid "Could not determine the recipient's e-mail address." msgstr "" #: lib/Horde/Crypt/Pgp.php:759 lib/Horde/Crypt/Pgp.php:848 msgid "Could not obtain public key from the keyserver." msgstr "" #: lib/Horde/Crypt/Smime.php:478 msgid "Country" msgstr "" #: lib/Horde/Crypt/Pgp.php:426 #, fuzzy msgid "E-Mail" msgstr "البريد" #: lib/Horde/Crypt/Smime.php:474 #, fuzzy msgid "Email Address" msgstr "عنوان بريدك الإلكتروني:" #: lib/Horde/Crypt/Pgp.php:1584 lib/Horde/Crypt/Pgp.php:1592 msgid "Error while talking to pgp binary." msgstr "" #: lib/Horde/Crypt/Smime.php:1251 lib/Horde/Crypt/Smime.php:1269 #: lib/Horde/Crypt/Smime.php:1284 msgid "Error while talking to smime binary." msgstr "" #: lib/Horde/Crypt/Pgp.php:425 msgid "Expiration Date" msgstr "" #: lib/Horde/Crypt/Smime.php:586 msgid "Exponent" msgstr "" #: lib/Horde/Crypt/Smime.php:484 msgid "Given Name" msgstr "" #: lib/Horde/Crypt/Pgp.php:426 msgid "Hash-Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:534 msgid "Issuer" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 msgid "Key Creation" msgstr "" #: lib/Horde/Crypt/Pgp.php:427 msgid "Key Fingerprint" msgstr "" #: lib/Horde/Crypt/Pgp.php:427 msgid "Key ID" msgstr "" #: lib/Horde/Crypt/Pgp.php:425 msgid "Key Length" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 msgid "Key Type" msgstr "" #: lib/Horde/Crypt/Smime.php:507 #, fuzzy msgid "Key Usage" msgstr "حجم الاستخدام:" #: lib/Horde/Crypt/Pgp.php:782 msgid "Key already exists on the public keyserver." msgstr "" #: lib/Horde/Crypt/Smime.php:480 msgid "Location" msgstr "" #: lib/Horde/Crypt/Smime.php:189 msgid "" "Message Verified Successfully but the signer's certificate could not be " "verified." msgstr "" #: lib/Horde/Crypt/Smime.php:583 msgid "Modulus" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 msgid "Name" msgstr "الاسم" #: lib/Horde/Crypt/Smime.php:490 msgid "Netscape Base URL" msgstr "" #: lib/Horde/Crypt/Smime.php:492 msgid "Netscape CA Revocation URL" msgstr "" #: lib/Horde/Crypt/Smime.php:494 msgid "Netscape CA policy URL" msgstr "" #: lib/Horde/Crypt/Smime.php:493 msgid "Netscape Renewal URL" msgstr "" #: lib/Horde/Crypt/Smime.php:491 msgid "Netscape Revocation URL" msgstr "" #: lib/Horde/Crypt/Smime.php:495 msgid "Netscape SSL server name" msgstr "" #: lib/Horde/Crypt/Smime.php:496 msgid "Netscape certificate comment" msgstr "" #: lib/Horde/Crypt/Smime.php:489 msgid "Netscape certificate type" msgstr "" #: lib/Horde/Crypt/Pgp.php:449 msgid "Never" msgstr "أبداً" #: lib/Horde/Crypt/Smime.php:1217 msgid "" "No path to the OpenSSL binary provided. The OpenSSL binary is necessary to " "work with PKCS 12 data." msgstr "" #: lib/Horde/Crypt/Pgp.php:451 lib/Horde/Crypt/Pgp.php:452 msgid "None" msgstr "" #: lib/Horde/Crypt/Smime.php:549 msgid "Not After" msgstr "" #: lib/Horde/Crypt/Smime.php:548 msgid "Not Before" msgstr "" #: lib/Horde/Crypt/Smime.php:231 msgid "OpenSSL error: Could not extract data from signed S/MIME part." msgstr "" #: lib/Horde/Crypt/Smime.php:476 msgid "Organisation" msgstr "" #: lib/Horde/Crypt/Smime.php:477 msgid "Organisational Unit" msgstr "" #: lib/Horde/Crypt/Pgp.php:1406 msgid "PGP Digital Signature" msgstr "" #: lib/Horde/Crypt/Pgp.php:1450 msgid "PGP Encrypted Data" msgstr "" #: lib/Horde/Crypt/Pgp.php:1511 msgid "PGP Public Key" msgstr "" #: lib/Horde/Crypt/Pgp.php:1493 msgid "PGP Signed/Encrypted Data" msgstr "" #: lib/Horde/Crypt/Smime.php:1256 #, fuzzy msgid "Password incorrect" msgstr "كلمة المرور" #: lib/Horde/Crypt/Pgp.php:447 msgid "Private Key" msgstr "" #: lib/Horde/Crypt/Pgp.php:447 msgid "Public Key" msgstr "" #: lib/Horde/Crypt/Smime.php:554 msgid "Public Key Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:553 msgid "Public Key Info" msgstr "" #: lib/Horde/Crypt/Pgp.php:225 msgid "Public/Private keypair not generated successfully." msgstr "" #: lib/Horde/Crypt/Smime.php:572 #, php-format msgid "RSA Public Key (%d bit)" msgstr "" #: lib/Horde/Crypt/Pgp.php:227 msgid "Returned error message:" msgstr "" #: lib/Horde/Crypt/Pgp.php:1644 msgid "Revocation key not generated successfully." msgstr "" #: lib/Horde/Crypt/Smime.php:252 msgid "S/MIME Cryptographic Signature" msgstr "" #: lib/Horde/Crypt/Smime.php:283 msgid "S/MIME Encrypted Message" msgstr "" #: lib/Horde/Crypt/Smime.php:611 msgid "Serial Number" msgstr "" #: lib/Horde/Crypt/Smime.php:622 msgid "Signature" msgstr "" #: lib/Horde/Crypt/Smime.php:621 msgid "Signature Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:479 msgid "State or Province" msgstr "" #: lib/Horde/Crypt/Smime.php:481 #, fuzzy msgid "Street Address" msgstr "عنوان المنزل" #: lib/Horde/Crypt/Smime.php:483 #, fuzzy msgid "Surname" msgstr "الاسم" #: lib/Horde/Crypt/Smime.php:482 msgid "Telephone Number" msgstr "" #: lib/Horde/Crypt/Pgp.php:1311 msgid "" "The detached PGP signature block is required to verify the signed message." msgstr "" #: lib/Horde/Crypt/Smime.php:1146 msgid "The openssl module is required for the Horde_Crypt_Smime:: class." msgstr "" #: lib/Horde/Crypt/Smime.php:512 msgid "Unable to extract certificate details" msgstr "" #: lib/Horde/Crypt/Pgp.php:453 lib/Horde/Crypt/Pgp.php:454 #: lib/Horde/Crypt/Pgp.php:455 msgid "Unknown" msgstr "" #: lib/Horde/Crypt/Smime.php:596 lib/Horde/Crypt/Smime.php:844 #: lib/Horde/Crypt/Smime.php:850 msgid "Unsupported Extension" msgstr "" #: lib/Horde/Crypt/Smime.php:547 msgid "Validity" msgstr "" #: lib/Horde/Crypt/Smime.php:191 msgid "Verification failed - an unknown error has occurred." msgstr "" #: lib/Horde/Crypt/Smime.php:193 msgid "Verification failed - this message may have been tampered with." msgstr "" #: lib/Horde/Crypt/Smime.php:610 msgid "Version" msgstr "" #: lib/Horde/Crypt/Smime.php:502 msgid "X509v3 Basic Constraints" msgstr "" #: lib/Horde/Crypt/Smime.php:501 msgid "X509v3 Extended Key Usage" msgstr "" #: lib/Horde/Crypt/Smime.php:503 msgid "X509v3 Subject Alternative Name" msgstr "" #: lib/Horde/Crypt/Smime.php:504 msgid "X509v3 Subject Key Identifier" msgstr "" #: lib/Horde/Crypt/Smime.php:592 msgid "X509v3 extensions" msgstr "" #: lib/Horde/Crypt/Smime.php:1135 msgid "not yet implemented" msgstr "" Horde_Crypt-2.4.0/locale/bg/LC_MESSAGES/Horde_Crypt.mo 0000664 0001750 0001750 00000004115 12242643672 020247 0 ustar jan jan 0 8 1 Q j + 3 / L + Z 2 J ? B O ^ L @ k { T f ] n A public PGP key is required to verify a signed message. A public PGP key, private PGP key, and passphrase are required to sign a message. Connection refused to the public keyserver. Could not determine the recipient's e-mail address. Could not obtain public key from the keyserver. Email Address Key already exists on the public keyserver. Name Never Public/Private keypair not generated successfully. The detached PGP signature block is required to verify the signed message. Verification failed - this message may have been tampered with. Project-Id-Version: Horde_Crypt Report-Msgid-Bugs-To: dev@lists.horde.org POT-Creation-Date: 2010-10-13 01:27+0200 PO-Revision-Date: 2010-10-13 01:27+0200 Last-Translator: Automatically generated Language-Team: i18n@lists.horde.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit За да проверите подписано писмо е необходим PGP ключ. За да подпишете писмо са необходими: публичен ключ, личен ключ и ключова фраза. Достъпа до публичния сървър беше отказан. Некоректен email адрес на получателя. Грешка при получаването на публичния ключ от ключ-сървъра. Еmail адрес Ключа вече съществува в публичния ключсървър. Име Никога Ключова двойка публичен/частен ключ не беше генерирана. Прикрепеният PGP подпис е необходим за да се провери подписаното писмо. Грешка при проверката - това писмо може да е било подправено. Horde_Crypt-2.4.0/locale/bg/LC_MESSAGES/Horde_Crypt.po 0000664 0001750 0001750 00000026101 12242643672 020251 0 ustar jan jan # Bulgarian translations for Horde_Crypt module. # Copyright 2010-2013 Horde LLC (http://www.horde.org/) # This file is distributed under the same license as the Horde_Crypt module. # Automatically generated, 2010. # msgid "" msgstr "" "Project-Id-Version: Horde_Crypt\n" "Report-Msgid-Bugs-To: dev@lists.horde.org\n" "POT-Creation-Date: 2010-10-13 01:27+0200\n" "PO-Revision-Date: 2010-10-13 01:27+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: i18n@lists.horde.org\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Horde/Crypt/Smime.php:614 #, php-format msgid "%s Fingerprint" msgstr "" #: lib/Horde/Crypt/Pgp.php:1240 #, fuzzy msgid "A passphrase is required to decrypt a message." msgstr "За да криптирате писмо е необходим публичен PGP ключ." #: lib/Horde/Crypt/Pgp.php:1307 msgid "A public PGP key is required to verify a signed message." msgstr "За да проверите подписано писмо е необходим PGP ключ." #: lib/Horde/Crypt/Pgp.php:1164 msgid "" "A public PGP key, private PGP key, and passphrase are required to sign a " "message." msgstr "" "За да подпишете писмо са необходими: публичен ключ, личен ключ и ключова " "фраза." #: lib/Horde/Crypt/Smime.php:311 #, fuzzy msgid "A public S/MIME key is required to encrypt a message." msgstr "За да криптирате писмо е необходим публичен SMIME ключ." #: lib/Horde/Crypt/Smime.php:422 #, fuzzy msgid "" "A public S/MIME key, private S/MIME key, and passphrase are required to " "decrypt a message." msgstr "" "За да декриптирате писмо са необходими: публичен SMIME ключ, личен SMIME " "ключ и ключова фраза." #: lib/Horde/Crypt/Smime.php:360 #, fuzzy msgid "" "A public S/MIME key, private S/MIME key, and passphrase are required to sign " "a message." msgstr "" "За да подпишете писмо са необходими: публичен SMIME ключ, личен SMIME ключ и " "ключова фраза." #: lib/Horde/Crypt/Smime.php:506 msgid "CRL Distribution Points" msgstr "" #: lib/Horde/Crypt/Smime.php:609 msgid "Certificate Details" msgstr "" #: lib/Horde/Crypt/Smime.php:520 msgid "Certificate Owner" msgstr "" #: lib/Horde/Crypt/Smime.php:505 msgid "Certificate Policies" msgstr "" #: lib/Horde/Crypt/Pgp.php:426 #, fuzzy msgid "Comment" msgstr "Команди:" #: lib/Horde/Crypt/Smime.php:475 msgid "Common Name" msgstr "" #: lib/Horde/Crypt/Pgp.php:939 msgid "Connection refused to the public keyserver." msgstr "Достъпа до публичния сървър беше отказан." #: lib/Horde/Crypt/Pgp.php:950 #, fuzzy, php-format msgid "Connection refused to the public keyserver. Reason: %s (%s)" msgstr "Достъпа до публичния сървър беше отказан." #: lib/Horde/Crypt/Pgp.php:1132 #, fuzzy msgid "Could not PGP encrypt message: " msgstr "Грешка при PGP криптирането на писмо." #: lib/Horde/Crypt/Pgp.php:1201 #, fuzzy msgid "Could not PGP sign message: " msgstr "Грешка при PGP подписването на писмо." #: lib/Horde/Crypt/Smime.php:330 #, fuzzy msgid "Could not S/MIME encrypt message." msgstr "Грешка при SMIME криптирането на писмо." #: lib/Horde/Crypt/Smime.php:391 #, fuzzy msgid "Could not S/MIME sign message." msgstr "Грешка при SMIME подписването на писмо." #: lib/Horde/Crypt/Pgp.php:1276 #, fuzzy msgid "Could not decrypt PGP data: " msgstr "Грешка при декриптирането на PGP данни." #: lib/Horde/Crypt/Smime.php:440 #, fuzzy msgid "Could not decrypt S/MIME data." msgstr "Грешка при декриптирането на SMIME данни." #: lib/Horde/Crypt/Pgp.php:659 msgid "Could not determine the recipient's e-mail address." msgstr "Некоректен email адрес на получателя." #: lib/Horde/Crypt/Pgp.php:759 lib/Horde/Crypt/Pgp.php:848 msgid "Could not obtain public key from the keyserver." msgstr "Грешка при получаването на публичния ключ от ключ-сървъра." #: lib/Horde/Crypt/Smime.php:478 msgid "Country" msgstr "" #: lib/Horde/Crypt/Pgp.php:426 #, fuzzy msgid "E-Mail" msgstr "Поща" #: lib/Horde/Crypt/Smime.php:474 msgid "Email Address" msgstr "Еmail адрес" #: lib/Horde/Crypt/Pgp.php:1584 lib/Horde/Crypt/Pgp.php:1592 msgid "Error while talking to pgp binary." msgstr "" #: lib/Horde/Crypt/Smime.php:1251 lib/Horde/Crypt/Smime.php:1269 #: lib/Horde/Crypt/Smime.php:1284 msgid "Error while talking to smime binary." msgstr "" #: lib/Horde/Crypt/Pgp.php:425 msgid "Expiration Date" msgstr "" #: lib/Horde/Crypt/Smime.php:586 msgid "Exponent" msgstr "" #: lib/Horde/Crypt/Smime.php:484 #, fuzzy msgid "Given Name" msgstr "Име на файл" #: lib/Horde/Crypt/Pgp.php:426 msgid "Hash-Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:534 msgid "Issuer" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 msgid "Key Creation" msgstr "" #: lib/Horde/Crypt/Pgp.php:427 msgid "Key Fingerprint" msgstr "" #: lib/Horde/Crypt/Pgp.php:427 msgid "Key ID" msgstr "" #: lib/Horde/Crypt/Pgp.php:425 msgid "Key Length" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 #, fuzzy msgid "Key Type" msgstr "Mime тип" #: lib/Horde/Crypt/Smime.php:507 #, fuzzy msgid "Key Usage" msgstr "Използване::" #: lib/Horde/Crypt/Pgp.php:782 msgid "Key already exists on the public keyserver." msgstr "Ключа вече съществува в публичния ключсървър." #: lib/Horde/Crypt/Smime.php:480 msgid "Location" msgstr "" #: lib/Horde/Crypt/Smime.php:189 #, fuzzy msgid "" "Message Verified Successfully but the signer's certificate could not be " "verified." msgstr "" "Писмото беше проверено успешно, но сертификата на подписа не беше потвърден." #: lib/Horde/Crypt/Smime.php:583 msgid "Modulus" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 msgid "Name" msgstr "Име" #: lib/Horde/Crypt/Smime.php:490 msgid "Netscape Base URL" msgstr "" #: lib/Horde/Crypt/Smime.php:492 msgid "Netscape CA Revocation URL" msgstr "" #: lib/Horde/Crypt/Smime.php:494 msgid "Netscape CA policy URL" msgstr "" #: lib/Horde/Crypt/Smime.php:493 msgid "Netscape Renewal URL" msgstr "" #: lib/Horde/Crypt/Smime.php:491 msgid "Netscape Revocation URL" msgstr "" #: lib/Horde/Crypt/Smime.php:495 msgid "Netscape SSL server name" msgstr "" #: lib/Horde/Crypt/Smime.php:496 msgid "Netscape certificate comment" msgstr "" #: lib/Horde/Crypt/Smime.php:489 msgid "Netscape certificate type" msgstr "" #: lib/Horde/Crypt/Pgp.php:449 msgid "Never" msgstr "Никога" #: lib/Horde/Crypt/Smime.php:1217 msgid "" "No path to the OpenSSL binary provided. The OpenSSL binary is necessary to " "work with PKCS 12 data." msgstr "" #: lib/Horde/Crypt/Pgp.php:451 lib/Horde/Crypt/Pgp.php:452 msgid "None" msgstr "" #: lib/Horde/Crypt/Smime.php:549 msgid "Not After" msgstr "" #: lib/Horde/Crypt/Smime.php:548 msgid "Not Before" msgstr "" #: lib/Horde/Crypt/Smime.php:231 msgid "OpenSSL error: Could not extract data from signed S/MIME part." msgstr "" #: lib/Horde/Crypt/Smime.php:476 #, fuzzy msgid "Organisation" msgstr "Администриране" #: lib/Horde/Crypt/Smime.php:477 msgid "Organisational Unit" msgstr "" #: lib/Horde/Crypt/Pgp.php:1406 msgid "PGP Digital Signature" msgstr "" #: lib/Horde/Crypt/Pgp.php:1450 msgid "PGP Encrypted Data" msgstr "" #: lib/Horde/Crypt/Pgp.php:1511 msgid "PGP Public Key" msgstr "" #: lib/Horde/Crypt/Pgp.php:1493 msgid "PGP Signed/Encrypted Data" msgstr "" #: lib/Horde/Crypt/Smime.php:1256 #, fuzzy msgid "Password incorrect" msgstr "Парола: " #: lib/Horde/Crypt/Pgp.php:447 msgid "Private Key" msgstr "" #: lib/Horde/Crypt/Pgp.php:447 msgid "Public Key" msgstr "" #: lib/Horde/Crypt/Smime.php:554 msgid "Public Key Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:553 msgid "Public Key Info" msgstr "" #: lib/Horde/Crypt/Pgp.php:225 msgid "Public/Private keypair not generated successfully." msgstr "Ключова двойка публичен/частен ключ не беше генерирана." #: lib/Horde/Crypt/Smime.php:572 #, php-format msgid "RSA Public Key (%d bit)" msgstr "" #: lib/Horde/Crypt/Pgp.php:227 msgid "Returned error message:" msgstr "" #: lib/Horde/Crypt/Pgp.php:1644 #, fuzzy msgid "Revocation key not generated successfully." msgstr "Ключова двойка публичен/частен ключ не беше генерирана." #: lib/Horde/Crypt/Smime.php:252 msgid "S/MIME Cryptographic Signature" msgstr "" #: lib/Horde/Crypt/Smime.php:283 #, fuzzy msgid "S/MIME Encrypted Message" msgstr "Грешка при SMIME криптирането на писмо." #: lib/Horde/Crypt/Smime.php:611 msgid "Serial Number" msgstr "" #: lib/Horde/Crypt/Smime.php:622 msgid "Signature" msgstr "" #: lib/Horde/Crypt/Smime.php:621 msgid "Signature Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:479 msgid "State or Province" msgstr "" #: lib/Horde/Crypt/Smime.php:481 #, fuzzy msgid "Street Address" msgstr "Домашен адрес" #: lib/Horde/Crypt/Smime.php:483 #, fuzzy msgid "Surname" msgstr "без име" #: lib/Horde/Crypt/Smime.php:482 msgid "Telephone Number" msgstr "" #: lib/Horde/Crypt/Pgp.php:1311 msgid "" "The detached PGP signature block is required to verify the signed message." msgstr "" "Прикрепеният PGP подпис е необходим за да се провери подписаното писмо." #: lib/Horde/Crypt/Smime.php:1146 #, fuzzy msgid "The openssl module is required for the Horde_Crypt_Smime:: class." msgstr "Модулът OpenSSL е необходим за Crypt_smime:: class." #: lib/Horde/Crypt/Smime.php:512 msgid "Unable to extract certificate details" msgstr "" #: lib/Horde/Crypt/Pgp.php:453 lib/Horde/Crypt/Pgp.php:454 #: lib/Horde/Crypt/Pgp.php:455 msgid "Unknown" msgstr "" #: lib/Horde/Crypt/Smime.php:596 lib/Horde/Crypt/Smime.php:844 #: lib/Horde/Crypt/Smime.php:850 msgid "Unsupported Extension" msgstr "" #: lib/Horde/Crypt/Smime.php:547 msgid "Validity" msgstr "" #: lib/Horde/Crypt/Smime.php:191 msgid "Verification failed - an unknown error has occurred." msgstr "" #: lib/Horde/Crypt/Smime.php:193 msgid "Verification failed - this message may have been tampered with." msgstr "Грешка при проверката - това писмо може да е било подправено." #: lib/Horde/Crypt/Smime.php:610 #, fuzzy msgid "Version" msgstr "Права" #: lib/Horde/Crypt/Smime.php:502 msgid "X509v3 Basic Constraints" msgstr "" #: lib/Horde/Crypt/Smime.php:501 msgid "X509v3 Extended Key Usage" msgstr "" #: lib/Horde/Crypt/Smime.php:503 msgid "X509v3 Subject Alternative Name" msgstr "" #: lib/Horde/Crypt/Smime.php:504 msgid "X509v3 Subject Key Identifier" msgstr "" #: lib/Horde/Crypt/Smime.php:592 msgid "X509v3 extensions" msgstr "" #: lib/Horde/Crypt/Smime.php:1135 msgid "not yet implemented" msgstr "" Horde_Crypt-2.4.0/locale/bs/LC_MESSAGES/Horde_Crypt.mo 0000664 0001750 0001750 00000001150 12242643672 020257 0 ustar jan jan T B 1 > G K R Z Email Address Location Name Never None Serial Number Project-Id-Version: Horde_Crypt Report-Msgid-Bugs-To: dev@lists.horde.org POT-Creation-Date: 2010-10-13 01:27+0200 PO-Revision-Date: 2010-10-13 01:27+0200 Last-Translator: Automatically generated Language-Team: i18n@lists.horde.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Email adresa Lokacija Ime Nikada Nijedan Serijski broj Horde_Crypt-2.4.0/locale/bs/LC_MESSAGES/Horde_Crypt.po 0000664 0001750 0001750 00000021705 12242643672 020272 0 ustar jan jan # Bosnian translations for Horde_Crypt module. # Copyright 2010-2013 Horde LLC (http://www.horde.org/) # This file is distributed under the same license as the Horde_Crypt module. # Automatically generated, 2010. # msgid "" msgstr "" "Project-Id-Version: Horde_Crypt\n" "Report-Msgid-Bugs-To: dev@lists.horde.org\n" "POT-Creation-Date: 2010-10-13 01:27+0200\n" "PO-Revision-Date: 2010-10-13 01:27+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: i18n@lists.horde.org\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Horde/Crypt/Smime.php:614 #, php-format msgid "%s Fingerprint" msgstr "" #: lib/Horde/Crypt/Pgp.php:1240 msgid "A passphrase is required to decrypt a message." msgstr "" #: lib/Horde/Crypt/Pgp.php:1307 msgid "A public PGP key is required to verify a signed message." msgstr "" #: lib/Horde/Crypt/Pgp.php:1164 msgid "" "A public PGP key, private PGP key, and passphrase are required to sign a " "message." msgstr "" #: lib/Horde/Crypt/Smime.php:311 msgid "A public S/MIME key is required to encrypt a message." msgstr "" #: lib/Horde/Crypt/Smime.php:422 msgid "" "A public S/MIME key, private S/MIME key, and passphrase are required to " "decrypt a message." msgstr "" #: lib/Horde/Crypt/Smime.php:360 msgid "" "A public S/MIME key, private S/MIME key, and passphrase are required to sign " "a message." msgstr "" #: lib/Horde/Crypt/Smime.php:506 msgid "CRL Distribution Points" msgstr "" #: lib/Horde/Crypt/Smime.php:609 msgid "Certificate Details" msgstr "" #: lib/Horde/Crypt/Smime.php:520 msgid "Certificate Owner" msgstr "" #: lib/Horde/Crypt/Smime.php:505 msgid "Certificate Policies" msgstr "" #: lib/Horde/Crypt/Pgp.php:426 msgid "Comment" msgstr "" #: lib/Horde/Crypt/Smime.php:475 #, fuzzy msgid "Common Name" msgstr "Vaše ime" #: lib/Horde/Crypt/Pgp.php:939 msgid "Connection refused to the public keyserver." msgstr "" #: lib/Horde/Crypt/Pgp.php:950 #, php-format msgid "Connection refused to the public keyserver. Reason: %s (%s)" msgstr "" #: lib/Horde/Crypt/Pgp.php:1132 msgid "Could not PGP encrypt message: " msgstr "" #: lib/Horde/Crypt/Pgp.php:1201 msgid "Could not PGP sign message: " msgstr "" #: lib/Horde/Crypt/Smime.php:330 msgid "Could not S/MIME encrypt message." msgstr "" #: lib/Horde/Crypt/Smime.php:391 msgid "Could not S/MIME sign message." msgstr "" #: lib/Horde/Crypt/Pgp.php:1276 #, fuzzy msgid "Could not decrypt PGP data: " msgstr "Nije bilo moguce obrisati poruke od %s: %s" #: lib/Horde/Crypt/Smime.php:440 msgid "Could not decrypt S/MIME data." msgstr "" #: lib/Horde/Crypt/Pgp.php:659 #, fuzzy msgid "Could not determine the recipient's e-mail address." msgstr "Nedozvoljena slova u email adresi." #: lib/Horde/Crypt/Pgp.php:759 lib/Horde/Crypt/Pgp.php:848 msgid "Could not obtain public key from the keyserver." msgstr "" #: lib/Horde/Crypt/Smime.php:478 msgid "Country" msgstr "" #: lib/Horde/Crypt/Pgp.php:426 #, fuzzy msgid "E-Mail" msgstr "Sanduce" #: lib/Horde/Crypt/Smime.php:474 msgid "Email Address" msgstr "Email adresa" #: lib/Horde/Crypt/Pgp.php:1584 lib/Horde/Crypt/Pgp.php:1592 msgid "Error while talking to pgp binary." msgstr "" #: lib/Horde/Crypt/Smime.php:1251 lib/Horde/Crypt/Smime.php:1269 #: lib/Horde/Crypt/Smime.php:1284 msgid "Error while talking to smime binary." msgstr "" #: lib/Horde/Crypt/Pgp.php:425 msgid "Expiration Date" msgstr "" #: lib/Horde/Crypt/Smime.php:586 msgid "Exponent" msgstr "" #: lib/Horde/Crypt/Smime.php:484 #, fuzzy msgid "Given Name" msgstr "Ime datoteke" #: lib/Horde/Crypt/Pgp.php:426 msgid "Hash-Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:534 msgid "Issuer" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 msgid "Key Creation" msgstr "" #: lib/Horde/Crypt/Pgp.php:427 msgid "Key Fingerprint" msgstr "" #: lib/Horde/Crypt/Pgp.php:427 msgid "Key ID" msgstr "" #: lib/Horde/Crypt/Pgp.php:425 msgid "Key Length" msgstr "" #: lib/Horde/Crypt/Pgp.php:424 #, fuzzy msgid "Key Type" msgstr "Mime tip" #: lib/Horde/Crypt/Smime.php:507 #, fuzzy msgid "Key Usage" msgstr "Poruka" #: lib/Horde/Crypt/Pgp.php:782 msgid "Key already exists on the public keyserver." msgstr "" #: lib/Horde/Crypt/Smime.php:480 msgid "Location" msgstr "Lokacija" #: lib/Horde/Crypt/Smime.php:189 msgid "" "Message Verified Successfully but the signer's certificate could not be " "verified." msgstr "" #: lib/Horde/Crypt/Smime.php:583 #, fuzzy msgid "Modulus" msgstr "Prebaci" #: lib/Horde/Crypt/Pgp.php:424 msgid "Name" msgstr "Ime" #: lib/Horde/Crypt/Smime.php:490 msgid "Netscape Base URL" msgstr "" #: lib/Horde/Crypt/Smime.php:492 msgid "Netscape CA Revocation URL" msgstr "" #: lib/Horde/Crypt/Smime.php:494 msgid "Netscape CA policy URL" msgstr "" #: lib/Horde/Crypt/Smime.php:493 msgid "Netscape Renewal URL" msgstr "" #: lib/Horde/Crypt/Smime.php:491 msgid "Netscape Revocation URL" msgstr "" #: lib/Horde/Crypt/Smime.php:495 msgid "Netscape SSL server name" msgstr "" #: lib/Horde/Crypt/Smime.php:496 msgid "Netscape certificate comment" msgstr "" #: lib/Horde/Crypt/Smime.php:489 msgid "Netscape certificate type" msgstr "" #: lib/Horde/Crypt/Pgp.php:449 msgid "Never" msgstr "Nikada" #: lib/Horde/Crypt/Smime.php:1217 msgid "" "No path to the OpenSSL binary provided. The OpenSSL binary is necessary to " "work with PKCS 12 data." msgstr "" #: lib/Horde/Crypt/Pgp.php:451 lib/Horde/Crypt/Pgp.php:452 msgid "None" msgstr "Nijedan" #: lib/Horde/Crypt/Smime.php:549 #, fuzzy msgid "Not After" msgstr "Not Draft" #: lib/Horde/Crypt/Smime.php:548 #, fuzzy msgid "Not Before" msgstr "Not Draft" #: lib/Horde/Crypt/Smime.php:231 msgid "OpenSSL error: Could not extract data from signed S/MIME part." msgstr "" #: lib/Horde/Crypt/Smime.php:476 #, fuzzy msgid "Organisation" msgstr "Registracija korisnika" #: lib/Horde/Crypt/Smime.php:477 msgid "Organisational Unit" msgstr "" #: lib/Horde/Crypt/Pgp.php:1406 #, fuzzy msgid "PGP Digital Signature" msgstr "Zatamni potpise?" #: lib/Horde/Crypt/Pgp.php:1450 msgid "PGP Encrypted Data" msgstr "" #: lib/Horde/Crypt/Pgp.php:1511 msgid "PGP Public Key" msgstr "" #: lib/Horde/Crypt/Pgp.php:1493 msgid "PGP Signed/Encrypted Data" msgstr "" #: lib/Horde/Crypt/Smime.php:1256 #, fuzzy msgid "Password incorrect" msgstr "Password" #: lib/Horde/Crypt/Pgp.php:447 msgid "Private Key" msgstr "" #: lib/Horde/Crypt/Pgp.php:447 msgid "Public Key" msgstr "" #: lib/Horde/Crypt/Smime.php:554 msgid "Public Key Algorithm" msgstr "" #: lib/Horde/Crypt/Smime.php:553 msgid "Public Key Info" msgstr "" #: lib/Horde/Crypt/Pgp.php:225 msgid "Public/Private keypair not generated successfully." msgstr "" #: lib/Horde/Crypt/Smime.php:572 #, php-format msgid "RSA Public Key (%d bit)" msgstr "" #: lib/Horde/Crypt/Pgp.php:227 #, fuzzy msgid "Returned error message:" msgstr "Čitanje poruka" #: lib/Horde/Crypt/Pgp.php:1644 msgid "Revocation key not generated successfully." msgstr "" #: lib/Horde/Crypt/Smime.php:252 msgid "S/MIME Cryptographic Signature" msgstr "" #: lib/Horde/Crypt/Smime.php:283 msgid "S/MIME Encrypted Message" msgstr "" #: lib/Horde/Crypt/Smime.php:611 msgid "Serial Number" msgstr "Serijski broj" #: lib/Horde/Crypt/Smime.php:622 #, fuzzy msgid "Signature" msgstr "Vaš potpis:" #: lib/Horde/Crypt/Smime.php:621 #, fuzzy msgid "Signature Algorithm" msgstr "Vaš potpis:" #: lib/Horde/Crypt/Smime.php:479 msgid "State or Province" msgstr "" #: lib/Horde/Crypt/Smime.php:481 #, fuzzy msgid "Street Address" msgstr "Od adrese" #: lib/Horde/Crypt/Smime.php:483 #, fuzzy msgid "Surname" msgstr "Username" #: lib/Horde/Crypt/Smime.php:482 #, fuzzy msgid "Telephone Number" msgstr "Serijski broj" #: lib/Horde/Crypt/Pgp.php:1311 msgid "" "The detached PGP signature block is required to verify the signed message." msgstr "" #: lib/Horde/Crypt/Smime.php:1146 msgid "The openssl module is required for the Horde_Crypt_Smime:: class." msgstr "" #: lib/Horde/Crypt/Smime.php:512 msgid "Unable to extract certificate details" msgstr "" #: lib/Horde/Crypt/Pgp.php:453 lib/Horde/Crypt/Pgp.php:454 #: lib/Horde/Crypt/Pgp.php:455 msgid "Unknown" msgstr "" #: lib/Horde/Crypt/Smime.php:596 lib/Horde/Crypt/Smime.php:844 #: lib/Horde/Crypt/Smime.php:850 msgid "Unsupported Extension" msgstr "" #: lib/Horde/Crypt/Smime.php:547 msgid "Validity" msgstr "" #: lib/Horde/Crypt/Smime.php:191 #, fuzzy msgid "Verification failed - an unknown error has occurred." msgstr "Došlo je do fatalne greške" #: lib/Horde/Crypt/Smime.php:193 msgid "Verification failed - this message may have been tampered with." msgstr "" #: lib/Horde/Crypt/Smime.php:610 #, fuzzy msgid "Version" msgstr "Lično" #: lib/Horde/Crypt/Smime.php:502 msgid "X509v3 Basic Constraints" msgstr "" #: lib/Horde/Crypt/Smime.php:501 msgid "X509v3 Extended Key Usage" msgstr "" #: lib/Horde/Crypt/Smime.php:503 msgid "X509v3 Subject Alternative Name" msgstr "" #: lib/Horde/Crypt/Smime.php:504 msgid "X509v3 Subject Key Identifier" msgstr "" #: lib/Horde/Crypt/Smime.php:592 msgid "X509v3 extensions" msgstr "" #: lib/Horde/Crypt/Smime.php:1135 #, fuzzy msgid "not yet implemented" msgstr "Ne izbrisana" Horde_Crypt-2.4.0/locale/ca/LC_MESSAGES/Horde_Crypt.mo 0000664 0001750 0001750 00000016000 12242643672 020236 0 ustar jan jan V | x y 8 Q Z W n ! + - ; Y ! 3 / ) Y a h v + Q r z & @ b F > # 9 L [ u 2 . G U _ s J % & < ? E B $ g D | c l % i 0 G d n ; x I ( ( ' ) P @ z > ( : C O a i { 8 d p w { # $ $ 6 [ { m K R ` u ! A > # 3 : P N 2 G H P m ' U L ) 0 O 1 > 3 K : I R D 5 ' $ 2 7 4 + A <