Get S/MIME encryption working #259

This commit is contained in:
the-djmaze 2024-02-20 12:38:57 +01:00
parent 196dffa8d8
commit 1762198642
4 changed files with 60 additions and 39 deletions

View file

@ -1545,24 +1545,34 @@ export class ComposePopupView extends AbstractViewPopup {
} }
} }
if (encrypt) { if (encrypt) {
Object.entries(PgpUserStore.getPublicKeyOfEmails(recipients) || {}).forEach(([k,v]) => const autocrypt = () =>
params.autocrypt.push({addr:k, keydata:v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g, '').trim()}) Object.entries(PgpUserStore.getPublicKeyOfEmails(recipients) || {}).forEach(([k,v]) =>
); params.autocrypt.push({
addr: k,
keydata: v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g, '').trim()
})
);
if ('openpgp' == encrypt) { if ('openpgp' == encrypt) {
// Doesn't encrypt attachments // Doesn't encrypt attachments
params.encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients); params.encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients);
params.signed = ''; params.signed = '';
autocrypt();
} else if ('gnupg' == encrypt) { } else if ('gnupg' == encrypt) {
// Does encrypt attachments // Does encrypt attachments
params.encryptFingerprints = JSON.stringify(GnuPGUserStore.getPublicKeyFingerprints(recipients)); params.encryptFingerprints = JSON.stringify(GnuPGUserStore.getPublicKeyFingerprints(recipients));
// } else { autocrypt();
// // S/MIME /*
// params.encryptCertificates = []; } else if (identity && identity.smimeCertificate()) {
// TODO: S/MIME certificates of all recipients
params.encryptCertificates = [identity.smimeCertificate()];
}
*/
} else { } else {
throw 'Encryption with ' + encrypt + ' not yet implemented'; throw 'Encryption with ' + encrypt + ' not yet implemented';
} }
} }
} }
return params; return params;
} }
} }

View file

@ -194,14 +194,14 @@ class Part
return \MailSo\Base\StreamWrappers\SubStreams::CreateStream($aSubStreams); return \MailSo\Base\StreamWrappers\SubStreams::CreateStream($aSubStreams);
} }
public function addEncrypted(string $sEncrypted, string $sType) public function addPgpEncrypted(string $sEncrypted)
{ {
$oPart = new self; $oPart = new self;
$oPart->Headers->AddByName(Enumerations\Header::CONTENT_TYPE, 'multipart/encrypted; protocol="'.$sType.'"'); $oPart->Headers->AddByName(Enumerations\Header::CONTENT_TYPE, 'multipart/encrypted; protocol="application/pgp-encrypted"');
$this->SubParts->append($oPart); $this->SubParts->append($oPart);
$oSubPart = new self; $oSubPart = new self;
$oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TYPE, $sType); $oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TYPE, 'application/pgp-encrypted');
$oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_DISPOSITION, 'attachment'); $oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_DISPOSITION, 'attachment');
$oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TRANSFER_ENCODING, '7Bit'); $oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TRANSFER_ENCODING, '7Bit');
$oSubPart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString('Version: 1'); $oSubPart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString('Version: 1');
@ -209,27 +209,12 @@ class Part
$oSubPart = new self; $oSubPart = new self;
$oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TYPE, 'application/octet-stream'); $oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TYPE, 'application/octet-stream');
if ('application/pgp-encrypted' === $sType) { $oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_DISPOSITION, 'inline; filename="msg.asc"');
$oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_DISPOSITION, 'inline; filename="msg.asc"');
}
if ('application/pkcs7-mime' === $sType) {
$oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_DISPOSITION, 'inline; filename="msg.p7m"');
}
$oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TRANSFER_ENCODING, '7Bit'); $oSubPart->Headers->AddByName(Enumerations\Header::CONTENT_TRANSFER_ENCODING, '7Bit');
$oSubPart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString($sEncrypted); $oSubPart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString($sEncrypted);
$oPart->SubParts->append($oSubPart); $oPart->SubParts->append($oSubPart);
} }
public function addPgpEncrypted(string $sEncrypted)
{
$this->addEncrypted($sEncrypted, 'application/pgp-encrypted');
}
public function addSMimeEncrypted(string $sEncrypted)
{
$this->addEncrypted($sEncrypted, 'application/pkcs7-mime');
}
public function addPlain(string $sPlain) public function addPlain(string $sPlain)
{ {
$oPart = new self; $oPart = new self;

View file

@ -1179,22 +1179,31 @@ trait Messages
} }
$oMessage->addPgpEncrypted($GPG->encryptStream($fp)); $oMessage->addPgpEncrypted($GPG->encryptStream($fp));
} else { } else {
$aCertificates = \json_decode($this->GetActionParam('encryptCertificates', ''), true); $aCertificates = $this->GetActionParam('encryptCertificates', []);
if ($aCertificates) { if ($aCertificates) {
$tmp = new \SnappyMail\File\Temporary('mimepart'); $oBody = $oMessage->GetRootPart();
$tmp->writeFromStream($oMessage->GetRootPart()->ToStream());
$resource = $oBody->ToStream();
\MailSo\Base\StreamFilters\LineEndings::appendTo($resource);
$tmp = new \SnappyMail\File\Temporary('mimepart');
$tmp->writeFromStream($resource);
$oBody->Body = null;
$oBody->SubParts->Clear();
$oMessage->SubParts->Clear(); $oMessage->SubParts->Clear();
$oMessage->Attachments()->Clear(); $oMessage->Attachments()->Clear();
$SMIME = $this->SMIME(); $SMIME = $this->SMIME();
/*
foreach ($aCertificates as $sCertificate) {
$SMIME->addEncryptKey($sCertificate);
}
*/
$sEncrypted = $SMIME->encrypt($tmp, $aCertificates); $sEncrypted = $SMIME->encrypt($tmp, $aCertificates);
$oMessage->addSMimeEncrypted($sEncrypted);
$oPart = new MimePart;
$oMessage->SubParts->append($oPart);
$oPart->Headers->AddByName(
MimeEnumHeader::CONTENT_TYPE,
'application/pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"'
);
$oPart->Headers->AddByName(MimeEnumHeader::CONTENT_TRANSFER_ENCODING, 'base64');
$oPart->Body = $sEncrypted;
} }
} }

View file

@ -162,7 +162,24 @@ class OpenSSL
)) { )) {
throw new \RuntimeException('OpenSSL encrypt: ' . \openssl_error_string()); throw new \RuntimeException('OpenSSL encrypt: ' . \openssl_error_string());
} }
return $output->getContents();
/**
* Only fetch the body part
*/
$fp = $output->fopen();
// Skip headers
while (\trim(\fgets($fp)));
// Fetch the body
$encrypted = '';
do {
$line = \fgets($fp);
if (!\trim($line)) {
return $encrypted;
}
$encrypted .= $line;
} while (true);
return $data;
} }
public function sign(/*string|Temporary*/$input, bool $detached = true) public function sign(/*string|Temporary*/$input, bool $detached = true)
@ -188,7 +205,7 @@ class OpenSSL
} }
/** /**
* Only fetch the signed part * Only fetch the signed body part
*/ */
$fp = $output->fopen(); $fp = $output->fopen();
$micalg = ''; $micalg = '';
@ -209,13 +226,13 @@ class OpenSSL
// Skip headers // Skip headers
while (\trim(\fgets($fp))); while (\trim(\fgets($fp)));
// Fetch the body // Fetch the body
$data = ''; $signature = '';
do { do {
$line = \fgets($fp); $line = \fgets($fp);
if (!\trim($line)) { if (!\trim($line)) {
return $data; return $signature;
} }
$data .= $line; $signature .= $line;
} while (true); } while (true);
} }
} }