2019-09-23 20:56:52 +02:00
|
|
|
<?php
|
|
|
|
class GpgTool
|
|
|
|
{
|
2020-05-03 20:03:17 +02:00
|
|
|
/**
|
2020-05-04 09:38:07 +02:00
|
|
|
* @return CryptGpgExtended
|
2020-05-03 20:03:17 +02:00
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function initializeGpg()
|
|
|
|
{
|
|
|
|
if (!class_exists('Crypt_GPG')) {
|
|
|
|
// 'Crypt_GPG' class cannot be autoloaded, try to require from include_path.
|
|
|
|
if (!stream_resolve_include_path('Crypt/GPG.php')) {
|
|
|
|
throw new Exception("Crypt_GPG is not installed.");
|
|
|
|
}
|
|
|
|
require_once 'Crypt/GPG.php';
|
|
|
|
}
|
|
|
|
|
2020-05-04 09:38:07 +02:00
|
|
|
require_once __DIR__ . '/CryptGpgExtended.php';
|
|
|
|
|
2020-05-03 20:03:17 +02:00
|
|
|
$homedir = Configure::read('GnuPG.homedir');
|
|
|
|
if ($homedir === null) {
|
|
|
|
throw new Exception("Configuration option 'GnuPG.homedir' is not set, Crypt_GPG cannot be initialized.");
|
|
|
|
}
|
|
|
|
|
|
|
|
$options = array(
|
|
|
|
'homedir' => $homedir,
|
|
|
|
'gpgconf' => Configure::read('GnuPG.gpgconf'),
|
|
|
|
'binary' => Configure::read('GnuPG.binary') ?: '/usr/bin/gpg',
|
|
|
|
);
|
|
|
|
|
2020-05-04 09:38:07 +02:00
|
|
|
return new CryptGpgExtended($options);
|
2020-05-03 20:03:17 +02:00
|
|
|
}
|
|
|
|
|
2019-09-23 20:56:52 +02:00
|
|
|
/**
|
|
|
|
* @param string $search
|
|
|
|
* @return array
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function searchGpgKey($search)
|
|
|
|
{
|
|
|
|
$uri = 'https://pgp.circl.lu/pks/lookup?search=' . urlencode($search) . '&op=index&fingerprint=on&options=mr';
|
|
|
|
$response = $this->keyServerLookup($uri);
|
|
|
|
if ($response->code == 404) {
|
|
|
|
return array(); // no keys found
|
|
|
|
} else if ($response->code != 200) {
|
|
|
|
throw new Exception("Fetching the '$uri' failed with HTTP error {$response->code}: {$response->reasonPhrase}");
|
|
|
|
}
|
|
|
|
return $this->extractKeySearch($response->body);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $fingerprint
|
|
|
|
* @return string|null
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function fetchGpgKey($fingerprint)
|
|
|
|
{
|
|
|
|
$uri = 'https://pgp.circl.lu/pks/lookup?search=0x' . urlencode($fingerprint) . '&op=get&options=mr';
|
|
|
|
$response = $this->keyServerLookup($uri);
|
|
|
|
if ($response->code == 404) {
|
|
|
|
return null; // key with given fingerprint not found
|
|
|
|
} else if ($response->code != 200) {
|
|
|
|
throw new Exception("Fetching the '$uri' failed with HTTP error {$response->code}: {$response->reasonPhrase}");
|
|
|
|
}
|
|
|
|
|
|
|
|
$key = $response->body;
|
|
|
|
|
|
|
|
return $key;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $body
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
private function extractKeySearch($body)
|
|
|
|
{
|
|
|
|
$final = array();
|
|
|
|
$lines = explode("\n", $body);
|
|
|
|
foreach ($lines as $line) {
|
|
|
|
$parts = explode(":", $line);
|
|
|
|
|
|
|
|
if ($parts[0] === 'pub') {
|
|
|
|
if (!empty($temp)) {
|
|
|
|
$final[] = $temp;
|
|
|
|
$temp = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strpos($parts[6], 'r') !== false || strpos($parts[6], 'd') !== false || strpos($parts[6], 'e') !== false) {
|
|
|
|
continue; // skip if key is expired, revoked or disabled
|
|
|
|
}
|
|
|
|
|
|
|
|
$temp = array(
|
|
|
|
'fingerprint' => $parts[1],
|
|
|
|
'key_id' => substr($parts[1], -8),
|
|
|
|
'date' => date('Y-m-d', $parts[4]),
|
|
|
|
);
|
|
|
|
|
|
|
|
} else if ($parts[0] === 'uid' && !empty($temp)) {
|
|
|
|
$temp['address'] = urldecode($parts[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!empty($temp)) {
|
|
|
|
$final[] = $temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $final;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $uri
|
|
|
|
* @return HttpSocketResponse
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
private function keyServerLookup($uri)
|
|
|
|
{
|
|
|
|
App::uses('SyncTool', 'Tools');
|
|
|
|
$syncTool = new SyncTool();
|
|
|
|
$HttpSocket = $syncTool->setupHttpSocket();
|
|
|
|
$response = $HttpSocket->get($uri);
|
|
|
|
if ($response === false) {
|
|
|
|
throw new Exception("Could not fetch '$uri'.");
|
|
|
|
}
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
}
|