Added DoGnupgDecrypt(), DoGetStoredPGPKeys() and DoStorePGPKey() for #89

This commit is contained in:
the-djmaze 2022-01-26 12:15:36 +01:00
parent 897c150b1e
commit 8dc949f15c
3 changed files with 138 additions and 2 deletions

View file

@ -696,12 +696,14 @@ trait Messages
'text' => \preg_replace('/\\R/s', "\r\n",
$oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sBodyPartId.']')
),
'signature' => false
'signature' => ''
];
}
if (\class_exists('gnupg')) {
$GPG = $this->GnuPG();
if ($GPG) {
$info = $this->GnuPG()->verify($result['text'], $result['signature'])[0];
// $info = $this->GnuPG()->verifyStream($fp, $result['signature'])[0];
/**
* https://code.woboq.org/qt5/include/gpg-error.h.html

View file

@ -4,6 +4,10 @@ namespace RainLoop\Actions;
trait Pgp
{
/**
* Also see trait Messages::DoMessagePgpVerify
*/
/**
* @throws \MailSo\Base\Exceptions\Exception
*/
@ -46,6 +50,43 @@ trait Pgp
return \SnappyMail\PGP\GnuPG::getInstance($homedir);
}
public function DoGnupgDecrypt() : array
{
$GPG = $this->GnuPG();
if (!$GPG) {
return $this->FalseResponse(__FUNCTION__);
}
$GPG->addDecryptKey(
$this->GetActionParam('KeyId', ''),
$this->GetActionParam('Passphrase', '')
);
$sData = $this->GetActionParam('Data', '');
$oPart = null;
if ($sData) {
$result = $GPG->decrypt($sData);
$oPart = \MailSo\Mime\Part::FromString($result);
} else {
$this->initMailClientConnection();
$this->MailClient()->MessageMimeStream(
function ($rResource) use ($GPG, $oPart) {
if (\is_resource($rResource)) {
$result = $GPG->decryptStream($rResource);
$oPart = \MailSo\Mime\Part::FromString($result);
// $GPG->decryptStream($rResource, $rStreamHandle);
// $oPart = \MailSo\Mime\Part::FromStream($rStreamHandle);
}
},
$this->GetActionParam('Folder', ''),
(int) $this->GetActionParam('Uid', ''),
$this->GetActionParam('PartId', '')
);
}
return $this->DefaultResponse(__FUNCTION__, $oPart);
}
public function DoGnupgGetKeys() : array
{
$GPG = $this->GnuPG();
@ -113,4 +154,74 @@ trait Pgp
? $this->DefaultResponse(__FUNCTION__, $GPG->import($sKey))
: $this->FalseResponse(__FUNCTION__);
}
/**
* Used to import keys in OpenPGP.js
* Handy when using multiple browsers
*/
public function DoGetStoredPGPKeys() : array
{
$oAccount = $this->getMainAccountFromToken();
if (!$oAccount) {
return null;
}
$dir = $this->StorageProvider()->GenerateFilePath(
$oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::PGP
);
$keys = [];
foreach (\glob("{$dir}/*") as $file) {
if (\is_file($file)) {
if ('.asc' === \substr($file, -4)) {
$keys[] = \file_get_contents($file);
} else if ('.key' === \substr($file, -4)) {
$data = \json_decode(\file_get_contents($file), true);
$mac = \array_pop($sKey);
$hash = $oAccount->CryptKey();
if ($mac === \hash_hmac('sha1', $data[2], $hash)) {
$keys[] = \SnappyMail\Crypt::Decrypt($data, $hash);
}
}
}
}
return $this->DefaultResponse(__FUNCTION__, $keys);
}
/**
* Used to store key from OpenPGP.js
* Handy when using multiple browsers
*/
public function DoStorePGPKey() : array
{
$oAccount = $this->getMainAccountFromToken();
if (!$oAccount) {
return null;
}
$key = $this->GetActionParam('Key', '');
$keyId = $this->GetActionParam('KeyId', '');
$result = false;
if ($key && $keyId) {
$dir = $this->StorageProvider()->GenerateFilePath(
$oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::PGP
);
if (\str_contains($key, 'PGP PRIVATE KEY')) {
$hash = $oAccount->CryptKey();
$key = \SnappyMail\Crypt::Encrypt($key, $hash);
$key[] = \hash_hmac('sha1', $key[2], $hash);
$result = \file_put_contents("{$dir}/0x{$keyId}.key", \json_encode($key));
} else if (\str_contains($key, 'PGP PUBLIC KEY')) {
$result = \file_put_contents("{$dir}/0x{$keyId}_public.asc", $key);
}
}
return $result
? $this->TrueResponse(__FUNCTION__)
: $this->FalseResponse(__FUNCTION__);
}
}

View file

@ -135,6 +135,17 @@ class GnuPG
: $this->GPG->decryptFile($filename);
}
/**
* Decrypts a given resource
*/
public function decryptStream(/*resource*/ $fp, /*string|resource*/ $output = null) /*: string|false */
{
if (!$fp || !\is_resource($fp)) {
throw new \Exception('Invalid stream resource');
}
return $this->getGPG()->decryptStream($fp, $output);
}
/**
* Decrypts and verifies a given text
*/
@ -404,4 +415,16 @@ class GnuPG
? $this->GnuPG->verify(\file_get_contents($filename), $signature, $plaintext)
: $this->GPG->verifyFile($filename, $signature, $plaintext);
}
/**
* Verifies a given resource
*/
public function verifyStream(/*resource*/ $fp, string $signature, string &$plaintext = null) /*: string|false */
{
if (!$fp || !\is_resource($fp)) {
throw new \Exception('Invalid stream resource');
}
return $this->getGPG()->verifyStream($fp, $signature, $plaintext);
}
}