Get decrypt working for #89

This commit is contained in:
the-djmaze 2022-01-25 14:46:03 +01:00
parent 54feb03316
commit b1a2b7da95

View file

@ -42,7 +42,6 @@ class GPG
$debug = false; $debug = false;
private private
$_commandBuffer,
$_message, $_message,
$_input, $_input,
$_output, $_output,
@ -148,6 +147,7 @@ class GPG
public function addDecryptKey(string $fingerprint, string $passphrase) : bool public function addDecryptKey(string $fingerprint, string $passphrase) : bool
{ {
$this->decryptKeys[$fingerprint] = $passphrase; $this->decryptKeys[$fingerprint] = $passphrase;
// $this->decryptKeys[\substr($fingerprint, -16)] = $passphrase;
return true; return true;
} }
@ -204,7 +204,7 @@ class GPG
$_ENV['PINENTRY_USER_DATA'] = \json_encode($this->decryptKeys); $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->decryptKeys);
$result = $this->exec('--decrypt --skip-verify'); $result = $this->exec(['--decrypt','--skip-verify']);
$fclose && \fclose($fclose); $fclose && \fclose($fclose);
@ -986,7 +986,7 @@ class GPG
$this->_debug('BEGIN PROCESSING'); $this->_debug('BEGIN PROCESSING');
$this->_commandBuffer = ''; // buffers input to GPG $commandBuffer = ''; // buffers input to GPG
$messageBuffer = ''; // buffers input to GPG $messageBuffer = ''; // buffers input to GPG
$inputBuffer = ''; // buffers input to GPG $inputBuffer = ''; // buffers input to GPG
$outputBuffer = ''; // buffers output from GPG $outputBuffer = ''; // buffers output from GPG
@ -1018,7 +1018,14 @@ class GPG
$delay = 0; $delay = 0;
$inputPosition = 0; $inputPosition = 0;
$start = \microtime(1);
while (true) { while (true) {
// Timeout after 5 seconds
if (5 < \microtime(1) - $start) {
exit('timeout');
}
$inputStreams = []; $inputStreams = [];
$outputStreams = []; $outputStreams = [];
$exceptionStreams = []; $exceptionStreams = [];
@ -1063,7 +1070,7 @@ class GPG
$outputStreams[] = $this->_output; $outputStreams[] = $this->_output;
} }
if ($this->_commandBuffer != '' && \is_resource($fdCommand)) { if ($commandBuffer != '' && \is_resource($fdCommand)) {
$outputStreams[] = $fdCommand; $outputStreams[] = $fdCommand;
} }
@ -1221,6 +1228,15 @@ class GPG
$line = \substr($line, 9); $line = \substr($line, 9);
$status[] = $line; $status[] = $line;
$this->debug && $this->_debug("\t{$line}"); $this->debug && $this->_debug("\t{$line}");
$tokens = \explode(' ', $line);
// NEED_PASSPHRASE 0123456789ABCDEF 0123456789ABCDEF 1 0
if ('NEED_PASSPHRASE' === $tokens[0]) {
// key ?: subkey
$passphrase = $this->getPassphrase($tokens[1]) ?: $this->getPassphrase($tokens[2]);
$commandBuffer .= $passphrase . PHP_EOL;
// $this->_openPipes->writePipe(self::FD_COMMAND, $passphrase . PHP_EOL);
}
} }
} }
} }
@ -1228,13 +1244,13 @@ class GPG
// write command (to GPG) // write command (to GPG)
if (\in_array($fdCommand, $outputStreams, true)) { if (\in_array($fdCommand, $outputStreams, true)) {
$this->_debug('GPG is ready for command data'); $this->_debug('GPG is ready for command data');
$chunk = \substr($this->_commandBuffer, 0, self::CHUNK_SIZE); $chunk = \substr($commandBuffer, 0, self::CHUNK_SIZE);
$length = \strlen($chunk); $length = \strlen($chunk);
$this->_debug('=> about to write ' . $length . ' bytes to GPG command'); $this->_debug('=> about to write ' . $length . ' bytes to GPG command');
$length = $this->_openPipes->writePipe(self::FD_COMMAND, $chunk, $length); $length = $this->_openPipes->writePipe(self::FD_COMMAND, $chunk, $length);
if ($length) { if ($length) {
$this->_debug('=> wrote ' . $length); $this->_debug('=> wrote ' . $length);
$this->_commandBuffer = \substr($this->_commandBuffer, $length); $commandBuffer = \substr($commandBuffer, $length);
} else { } else {
$this->_debug('=> pipe broken and closed'); $this->_debug('=> pipe broken and closed');
} }
@ -1263,7 +1279,6 @@ class GPG
$this->_message = null; $this->_message = null;
$this->_input = null; $this->_input = null;
$this->_output = null; $this->_output = null;
$this->_commandBuffer = '';
return [ return [
'output' => $outputBuffer, 'output' => $outputBuffer,
@ -1272,6 +1287,23 @@ class GPG
]; ];
} }
private function getPassphrase($key)
{
$passphrase = '';
$keyIdLength = \strlen($key);
if ($keyIdLength && !empty($_ENV['PINENTRY_USER_DATA'])) {
$passphrases = \json_decode($_ENV['PINENTRY_USER_DATA'], true);
foreach ($passphrases as $keyId => $pass) {
$length = \min($keyIdLength, \strlen($keyId));
if (\substr($keyId, -$length) === \substr($key, -$length)) {
return $pass;
}
}
}
// throw new \Exception("Passphrase not found for {$key}");
return '';
}
private function proc_close() : int private function proc_close() : int
{ {
$exitCode = 0; $exitCode = 0;