mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-30 20:49:20 +03:00
#89 verify detached signature using GnuPG
This commit is contained in:
parent
08ea226dbe
commit
93db6e6e0e
6 changed files with 82 additions and 71 deletions
|
|
@ -32,15 +32,6 @@ const
|
|||
return result;
|
||||
},
|
||||
|
||||
SignedVerifyStatus = {
|
||||
UnknownPublicKeys: -4,
|
||||
UnknownPrivateKey: -3,
|
||||
Unverified: -2,
|
||||
Error: -1,
|
||||
None: 0,
|
||||
Success: 1
|
||||
},
|
||||
|
||||
replyHelper = (emails, unic, localEmails) => {
|
||||
emails.forEach(email => {
|
||||
if (undefined === unic[email.email]) {
|
||||
|
|
@ -87,8 +78,7 @@ export class MessageModel extends AbstractModel {
|
|||
pgpSigned: null,
|
||||
pgpEncrypted: null,
|
||||
isPgpEncrypted: false,
|
||||
pgpSignedVerifyStatus: SignedVerifyStatus.None,
|
||||
pgpSignedVerifyUser: '',
|
||||
pgpVerified: null,
|
||||
|
||||
readReceipt: '',
|
||||
|
||||
|
|
@ -166,8 +156,7 @@ export class MessageModel extends AbstractModel {
|
|||
this.pgpSigned(null);
|
||||
this.pgpEncrypted(null);
|
||||
this.isPgpEncrypted(false);
|
||||
this.pgpSignedVerifyStatus(SignedVerifyStatus.None);
|
||||
this.pgpSignedVerifyUser('');
|
||||
this.pgpVerified(null);
|
||||
|
||||
this.priority(MessagePriority.Normal);
|
||||
this.readReceipt('');
|
||||
|
|
|
|||
|
|
@ -184,7 +184,21 @@ export const GnuPGUserStore = new class {
|
|||
}
|
||||
}
|
||||
|
||||
verify(/*message, fCallback*/) {
|
||||
async verify(message) {
|
||||
let data = message.pgpSigned(); // { BodyPartId: "1", SigPartId: "2", MicAlg: "pgp-sha256" }
|
||||
if (data) {
|
||||
// const sender = message.from[0].email;
|
||||
// let mode = await this.hasPublicKeyForEmails([sender]);
|
||||
data.Folder = message.folder;
|
||||
data.Uid = message.uid;
|
||||
let response = await Remote.post('MessagePgpVerify', null, data);
|
||||
if (response && response.Result) {
|
||||
return {
|
||||
fingerprint: response.Result.fingerprint,
|
||||
success: 0 == response.Result.status // GOODSIG
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -175,6 +175,47 @@ export const PgpUserStore = new class {
|
|||
return GnuPGUserStore.decrypt(message);
|
||||
}
|
||||
|
||||
async verify(message) {
|
||||
const plain = message.plain();
|
||||
if (/-----BEGIN PGP SIGNED MESSAGE-----/.test(plain) && /-----BEGIN PGP SIGNATURE-----/.test(plain)) {
|
||||
let result = await OpenPGPUserStore.verify(plain);
|
||||
console.dir(result);
|
||||
}
|
||||
if (message.pgpSigned()) {
|
||||
const sender = message.from[0].email;
|
||||
let mode = await this.hasPublicKeyForEmails([sender]);
|
||||
if ('gnupg' === mode) {
|
||||
return GnuPGUserStore.verify(message);
|
||||
}
|
||||
if ('openpgp' === mode) {
|
||||
const publicKey = OpenPGPUserStore.getPublicKeyFor(sender);
|
||||
OpenPGPUserStore.verify(plain, null/*detachedSignature*/, publicKey).then(result => {
|
||||
if (result) {
|
||||
message.plain(result.data);
|
||||
message.viewPlain();
|
||||
console.dir({signatures:result.signatures});
|
||||
}
|
||||
/*
|
||||
if (validKey) {
|
||||
i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', {
|
||||
USER: validKey.user + ' (' + validKey.id + ')'
|
||||
});
|
||||
message.getText()
|
||||
} else {
|
||||
const keyIds = arrayLength(signingKeyIds) ? signingKeyIds : null,
|
||||
additional = keyIds
|
||||
? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(v => v).join(', ')
|
||||
: '';
|
||||
|
||||
i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE') + (additional ? ' (' + additional + ')' : '');
|
||||
}
|
||||
*/
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an iframe with an editor for a new encrypted mail.
|
||||
* The iframe will be injected into the container identified by selector.
|
||||
|
|
|
|||
|
|
@ -436,14 +436,6 @@ html.rl-no-preview-pane {
|
|||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
&.success {
|
||||
color: green;
|
||||
}
|
||||
|
||||
&.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
span {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
|
@ -460,6 +452,19 @@ html.rl-no-preview-pane {
|
|||
border: 1px dashed #FA0;
|
||||
color: #FA0;
|
||||
}
|
||||
|
||||
&.success {
|
||||
border-color: #090;
|
||||
color: #090;
|
||||
}
|
||||
&.error {
|
||||
border-color: #F00;
|
||||
color: #F00;
|
||||
}
|
||||
&.error button,
|
||||
&.success button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.b-text-part > iframe {
|
||||
min-height: 50vh;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ import { decorateKoCommands, createCommand } from 'Knoin/Knoin';
|
|||
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||
|
||||
import { PgpUserStore } from 'Stores/User/Pgp';
|
||||
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
||||
|
||||
import PostalMime from '../../../../vendors/postal-mime/src/postal-mime.js';
|
||||
import { AttachmentModel } from 'Model/Attachment';
|
||||
|
|
@ -61,11 +60,12 @@ const
|
|||
currentMessage = () => MessageUserStore.message(),
|
||||
|
||||
mimeToMessage = (data, message) => {
|
||||
// TODO: Check multipart/signed
|
||||
// TODO: Check multipart/signed application/pgp-signature application/pgp-keys
|
||||
const headers = data.split(/\r?\n\r?\n/)[0];
|
||||
if (/Content-Type:.+; boundary=/.test(headers)) {
|
||||
// https://github.com/postalsys/postal-mime
|
||||
(new PostalMime).parse(data).then(result => {
|
||||
// TODO: multipart/signed
|
||||
let html = result.html,
|
||||
regex = /^<+|>+$/g;
|
||||
result.attachments.forEach(data => {
|
||||
|
|
@ -90,7 +90,6 @@ const
|
|||
});
|
||||
message.hasAttachments(message.attachments().hasVisible());
|
||||
// result.headers;
|
||||
// TODO: strip script tags and all other security that PHP also does
|
||||
message.plain(result.text || '');
|
||||
if (html) {
|
||||
message.html(html.replace(/<\/?script[\s\S]*?>/gi, '') || '');
|
||||
|
|
@ -639,51 +638,14 @@ export class MailMessageView extends AbstractViewRight {
|
|||
});
|
||||
}
|
||||
|
||||
pgpVerify() {
|
||||
const oMessage = currentMessage();
|
||||
if (oMessage.pgpSigned()) {
|
||||
const sender = oMessage.from[0].email;
|
||||
PgpUserStore.hasPublicKeyForEmails([oMessage.from[0].email]).then(mode => {
|
||||
if ('gnupg' === mode) {
|
||||
let params = oMessage.pgpSigned(); // { BodyPartId: "1", SigPartId: "2", MicAlg: "pgp-sha256" }
|
||||
params.Folder = oMessage.folder;
|
||||
params.Uid = oMessage.uid;
|
||||
rl.app.Remote.post('MessagePgpVerify', null, params)
|
||||
.then(data => {
|
||||
// TODO
|
||||
console.dir(data);
|
||||
})
|
||||
.catch(error => {
|
||||
// TODO
|
||||
console.dir(error);
|
||||
});
|
||||
} else if ('openpgp' === mode) {
|
||||
const publicKey = OpenPGPUserStore.getPublicKeyFor(sender);
|
||||
OpenPGPUserStore.verify(oMessage.plain(), null/*detachedSignature*/, publicKey).then(result => {
|
||||
if (result) {
|
||||
oMessage.plain(result.data);
|
||||
oMessage.viewPlain();
|
||||
console.dir({signatures:result.signatures});
|
||||
}
|
||||
/*
|
||||
if (validKey) {
|
||||
i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', {
|
||||
USER: validKey.user + ' (' + validKey.id + ')'
|
||||
});
|
||||
oMessage.getText()
|
||||
} else {
|
||||
const keyIds = arrayLength(signingKeyIds) ? signingKeyIds : null,
|
||||
additional = keyIds
|
||||
? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(v => v).join(', ')
|
||||
: '';
|
||||
|
||||
i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE') + (additional ? ' (' + additional + ')' : '');
|
||||
}
|
||||
*/
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
pgpVerify(/*self, event*/) {
|
||||
const oMessage = currentMessage()/*, ctrl = event.target.closest('.openpgp-control')*/;
|
||||
PgpUserStore.verify(oMessage).then(result => {
|
||||
console.dir({result:result});
|
||||
if (result) {
|
||||
oMessage.pgpVerified(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue