From 464d22d69a0a7c8ff866c3699fcf09126a75945d Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 4 Mar 2024 10:14:14 +0100 Subject: [PATCH] GPG use pinentries for decrypt, sign and export --- .../app/libraries/snappymail/gpg/base.php | 53 ++++++++++++++----- .../app/libraries/snappymail/gpg/pgp.php | 22 ++++---- .../app/libraries/snappymail/gpg/smime.php | 22 ++++---- .../libraries/snappymail/pgp/pgpinterface.php | 1 + 4 files changed, 62 insertions(+), 36 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php index 2518677a7..f82479cf1 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php @@ -43,10 +43,8 @@ abstract class Base protected $binary, $version = '2.0', - $passphrases = [], - $signKeys = [], + $pinentries = [], $encryptKeys = [], - $decryptKeys = [], // Create PEM encoded output $armor = true, @@ -284,8 +282,7 @@ abstract class Base */ public function addDecryptKey(string $fingerprint, SensitiveString $passphrase) : bool { - $this->decryptKeys[$fingerprint] = $passphrase; -// $this->decryptKeys[\substr($fingerprint, -16)] = $passphrase; + $this->addPinentry($fingerprint, $passphrase); return true; } @@ -303,9 +300,15 @@ abstract class Base */ public function addSignKey(string $fingerprint, SensitiveString $passphrase) : bool { - $this->signKeys[$fingerprint] = $passphrase; -// $this->signKeys[\substr($fingerprint, -16)] = $passphrase; - return false; + $this->addPinentry($fingerprint, $passphrase); + return true; + } + + public function clear() : bool + { + $this->clearPinentries(); + $this->clearEncryptKeys(); + return true; } /** @@ -313,8 +316,7 @@ abstract class Base */ public function clearDecryptKeys() : bool { - $this->decryptKeys = []; - return true; + return $this->clearPinentries(); } /** @@ -331,8 +333,7 @@ abstract class Base */ public function clearSignKeys() : bool { - $this->signKeys = []; - return true; + return $this->clearPinentries(); } /** @@ -348,12 +349,36 @@ abstract class Base ]; } - public function addPassphrase($keyId, SensitiveString $passphrase) + /** + * Add private key passphrase for decrypt, sign or export + * $keyId or fingerprint + */ + public function addPinentry(string $keyId, SensitiveString $passphrase) { - $this->passphrases[$keyId] = $passphrase; + /** + * Test first? + * gpg --dry-run --passwd + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', [$keyId => $passphrase])); + $result = $this->exec([ + '--dry-run', + '--passwd', + $fingerprint + ]); + */ + $this->pinentries[$keyId] = $passphrase; +// $this->pinentries[\substr($keyId, -16)] = $passphrase; return $this; } + /** + * Removes all keys which were set for decryption, signing and export + */ + public function clearPinentries() : bool + { + $this->pinentries = []; + return true; + } + /** * Toggle the armored output * When true the output is ASCII diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php index 587000ce2..1e4070278 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php @@ -96,8 +96,8 @@ class PGP extends Base implements \SnappyMail\PGP\PGPInterface $fclose = $this->setOutput($output); - if ($this->decryptKeys) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->decryptKeys)); + if ($this->pinentries) { + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->pinentries)); } $result = $this->exec(['--decrypt','--skip-verify']); @@ -244,8 +244,8 @@ class PGP extends Base implements \SnappyMail\PGP\PGPInterface if (!$keys) { throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId); } - if ($private && $this->passphrases) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->passphrases)); + if ($private && $this->pinentries) { + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->pinentries)); } $result = $this->exec([ $private ? '--export-secret-keys' : '--export', @@ -263,7 +263,7 @@ class PGP extends Base implements \SnappyMail\PGP\PGPInterface // \SnappyMail\Log::debug('GnuPG', "export({$fingerprint}, {$passphrase})"); if (null !== $passphrase) { return $this - ->addPassphrase($fingerprint, $passphrase) + ->addPinentry($fingerprint, $passphrase) ->_exportKey($fingerprint, true); } return $this->_exportKey($fingerprint); @@ -365,8 +365,8 @@ class PGP extends Base implements \SnappyMail\PGP\PGPInterface { $arguments = ['--import']; - if ($this->passphrases) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->passphrases)); + if ($this->pinentries) { + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->pinentries)); } else { $arguments[] = '--batch'; } @@ -618,7 +618,7 @@ class PGP extends Base implements \SnappyMail\PGP\PGPInterface protected function _sign(/*string|resource*/ $input, /*string|resource*/ $output = null, bool $textmode = true) /*: string|false*/ { - if (empty($this->signKeys)) { + if (empty($this->pinentries)) { throw new \Exception('No signing keys specified.'); } @@ -649,11 +649,11 @@ class PGP extends Base implements \SnappyMail\PGP\PGPInterface $arguments[] = '--textmode'; } - if ($this->signKeys) { - foreach ($this->signKeys as $fingerprint => $pass) { + if ($this->pinentries) { + foreach ($this->pinentries as $fingerprint => $pass) { $arguments[] = '--local-user ' . \escapeshellarg($fingerprint); } - $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->signKeys)); + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->pinentries)); } $result = $this->exec($arguments); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php index 3e8d76f5e..9160545b9 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php @@ -97,8 +97,8 @@ class SMIME extends Base $fclose = $this->setOutput($output); - if ($this->decryptKeys) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->decryptKeys); + if ($this->pinentries) { + $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->pinentries); } $result = $this->exec(['--decrypt','--skip-verify']); @@ -243,8 +243,8 @@ class SMIME extends Base if (!$keys) { throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId); } - if ($private && $this->passphrases) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->passphrases); + if ($private && $this->pinentries) { + $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->pinentries); } $result = $this->exec([ $private ? '--export-secret-key-p12' : '--export', @@ -261,7 +261,7 @@ class SMIME extends Base { if ($passphrase) { return $this - ->addPassphrase($fingerprint, $passphrase) + ->addPinentry($fingerprint, $passphrase) ->_exportKey($fingerprint, true); } return $this->_exportKey($fingerprint); @@ -271,8 +271,8 @@ class SMIME extends Base { $arguments = ['--import']; - if ($this->passphrases) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->passphrases); + if ($this->pinentries) { + $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->pinentries); } else { $arguments[] = '--batch'; } @@ -482,7 +482,7 @@ class SMIME extends Base protected function _sign(/*string|resource*/ $input, /*string|resource*/ $output = null) /*: string|false*/ { - if (empty($this->signKeys)) { + if (empty($this->pinentries)) { throw new \Exception('No signing keys specified.'); } @@ -498,11 +498,11 @@ class SMIME extends Base $arguments[] = '--armor'; } - if ($this->signKeys) { - foreach ($this->signKeys as $fingerprint => $pass) { + if ($this->pinentries) { + foreach ($this->pinentries as $fingerprint => $pass) { $arguments[] = '--local-user ' . \escapeshellarg($fingerprint); } - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->signKeys); + $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->pinentries); } $result = $this->exec($arguments); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php index 50fc1350e..3e7d31f6a 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php @@ -7,6 +7,7 @@ use SnappyMail\SensitiveString; interface PGPInterface { public static function isSupported() : bool; +// public function addPinentry(string $keyId, SensitiveString $passphrase) : bool; public function addDecryptKey(string $fingerprint, SensitiveString $passphrase) : bool; public function addEncryptKey(string $fingerprint) : bool; public function addSignKey(string $fingerprint, SensitiveString $passphrase) : bool;