/**
* 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."));
}