#89 add OpenPGP.js sign and encrypt

This commit is contained in:
the-djmaze 2022-02-07 11:32:53 +01:00
parent 4b030c93ff
commit 0cf63dab76
2 changed files with 52 additions and 17 deletions

View file

@ -47,7 +47,7 @@ import { ContactsPopupView } from 'View/Popup/Contacts';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
const const
base64_encode = text => btoa(text).match(/.{1,76}/g), base64_encode = text => btoa(text).match(/.{1,76}/g).join('\r\n'),
/** /**
* @param {string} prefix * @param {string} prefix
@ -99,6 +99,34 @@ ko.extenders.toggleSubscribe = (target, options) => {
return target; return target;
}; };
class MimePart {
constructor() {
this.headers = {};
this.body = '';
this.children = [];
}
toString() {
const hasSub = this.children.length,
boundary = 'part' + Jua.randomId(),
headers = this.headers;
if (hasSub) {
headers['Content-Type'] = headers['Content-Type'] + `; boundary="${boundary}"`;
}
let result =
Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join('\r\n')
+ '\r\n\r\n'
+ this.body;
if (hasSub) {
this.children.forEach(part => {
result = result + '\r\n--' + boundary + '\r\n' + part
});
result = result + '\r\n--' + boundary + '--\r\n';
}
return result;
}
}
class ComposePopupView extends AbstractViewPopup { class ComposePopupView extends AbstractViewPopup {
constructor() { constructor() {
super('Compose'); super('Compose');
@ -169,8 +197,8 @@ class ComposePopupView extends AbstractViewPopup {
showReplyTo: false, showReplyTo: false,
pgpSign: false, pgpSign: false,
pgpEncrypt: false,
canPgpSign: false, canPgpSign: false,
pgpEncrypt: false,
canPgpEncrypt: false, canPgpEncrypt: false,
canMailvelope: false, canMailvelope: false,
@ -386,21 +414,24 @@ class ComposePopupView extends AbstractViewPopup {
if (sign && 'openpgp' != sign[0]) { if (sign && 'openpgp' != sign[0]) {
throw 'Signing with ' + sign[0] + ' not yet implemented'; throw 'Signing with ' + sign[0] + ' not yet implemented';
} }
if (sign && sign[1]) { let data = new MimePart;
if (TextIsHtml) { data.headers['Content-Type'] = 'text/'+(TextIsHtml?'html':'plain')+'; charset="utf-8"';
throw 'Encrypt HTML with ' + encrypt + ' not yet implemented'; data.headers['Content-Transfer-Encoding'] = 'base64';
} data.body = base64_encode(Text);
Text = await OpenPGPUserStore.encrypt(Text, recipients, sign[1]); if (TextIsHtml && sign && sign[1]) {
// throw i18n('PGP_NOTIFICATIONS/PGP_ERROR', { ERROR: 'Encryption failed' }) let signed = new MimePart;
} else { signed.headers['Content-Type'] =
let data = [ 'multipart/signed; micalg="pgp-sha256"; protocol="application/pgp-signature"';
'Content-Transfer-Encoding: base64', signed.headers['Content-Transfer-Encoding'] = '7Bit';
'Content-Type: text/'+(TextIsHtml?'html':'plain')+'; charset="utf-8"', signed.children.push(data);
'', let signature = new MimePart;
base64_encode(Text) signature.headers['Content-Type'] = 'application/pgp-signature; name="signature.asc"';
].join("\r\n"); signature.headers['Content-Transfer-Encoding'] = '7Bit';
params.Encrypted = await OpenPGPUserStore.encrypt(data, recipients, sign && sign[1]); signature.body = await OpenPGPUserStore.sign(data.toString(), sign[1], 1);
signed.children.push(signature);
data = signed;
} }
params.Encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients);
} else { } else {
params.Html = TextIsHtml ? Text : ''; params.Html = TextIsHtml ? Text : '';
params.Text = TextIsHtml ? '' : Text; params.Text = TextIsHtml ? '' : Text;
@ -543,6 +574,10 @@ class ComposePopupView extends AbstractViewPopup {
params, params,
200000 200000
); );
}).catch(e => {
this.saving(false);
this.savedError(true);
this.savedErrorDesc(getNotification(Notification.CantSaveMessage) + ': ' + e);
}); });
} }
} }

View file

@ -211,7 +211,7 @@ class GPG
$fclose && \fclose($fclose); $fclose && \fclose($fclose);
return $output ? true : $result['output']; return $output ? true : ($result ? $result['output'] : false);
} }
/** /**