Verify S/MIME signed messages #259

This commit is contained in:
the-djmaze 2024-02-19 15:14:11 +01:00
parent 4df3766231
commit f53d9ed6c3
56 changed files with 769 additions and 433 deletions

View file

@ -292,6 +292,8 @@ viewMessage = (oMessage, popup) => {
class:'b-text-part'
+ (oMessage.pgpSigned() ? ' openpgp-signed' : '')
+ (oMessage.pgpEncrypted() ? ' openpgp-encrypted' : '')
+ (oMessage.smimeSigned() ? ' smime-signed' : '')
+ (oMessage.smimeEncrypted() ? ' smime-encrypted' : '')
});
MessageUserStore.purgeCache();
}

View file

@ -122,6 +122,10 @@ export class MessageModel extends AbstractModel {
pgpEncrypted: null,
pgpDecrypted: false,
smimeSigned: null,
smimeVerified: null,
smimeEncrypted: null,
// rfc8621
id: '',
// threadId: ''

View file

@ -14,11 +14,11 @@ import { AskPopupView } from 'View/Popup/Ask';
import { Passphrases } from 'Storage/Passphrases';
const
askPassphrase = async (privateKey, btnTxt = 'LABEL_SIGN') => {
askPassphrase = async (privateKey, btnTxt = 'SIGN') => {
const key = privateKey.id,
pass = Passphrases.has(key)
? {password:Passphrases.get(key), remember:false}
: await AskPopupView.password('GnuPG key<br>' + key + ' ' + privateKey.emails[0], 'OPENPGP/'+btnTxt);
: await AskPopupView.password('GnuPG key<br>' + key + ' ' + privateKey.emails[0], 'CRYPTO/'+btnTxt);
pass && pass.remember && Passphrases.set(key, pass.password);
return pass?.password;
},
@ -180,7 +180,7 @@ export const GnuPGUserStore = new class {
uid: message.uid,
partId: pgpInfo.partId,
keyId: key.id,
passphrase: await askPassphrase(key, 'BUTTON_DECRYPT'),
passphrase: await askPassphrase(key, 'DECRYPT'),
data: '' // message.plain() optional
}
if (null !== params.passphrase) {

View file

@ -20,7 +20,7 @@ const
key.emails.includes(query) || query == key.id || query == key.fingerprint
),
decryptKey = async (privateKey, btnTxt = 'LABEL_SIGN') => {
decryptKey = async (privateKey, btnTxt = 'SIGN') => {
if (privateKey.key.isDecrypted()) {
return privateKey.key;
}
@ -29,7 +29,7 @@ const
? {password:Passphrases.get(key), remember:false}
: await AskPopupView.password(
'OpenPGP.js key<br>' + key + ' ' + privateKey.emails[0],
'OPENPGP/'+btnTxt
'CRYPTO/'+btnTxt
);
if (pass) {
const passphrase = pass.password,
@ -210,7 +210,7 @@ export const OpenPGPUserStore = new class {
}
}
if (privateKey) try {
const decryptedKey = await decryptKey(privateKey, 'BUTTON_DECRYPT');
const decryptedKey = await decryptKey(privateKey, 'DECRYPT');
if (decryptedKey) {
const publicKey = findOpenPGPKey(this.publicKeys, sender/*, sign*/);
return await openpgp.decrypt({

View file

@ -1538,7 +1538,7 @@ export class ComposePopupView extends AbstractViewPopup {
} else if (this.canSMimeSign()) {
params.signCertificate = identity.smimeCertificate();
params.signPrivateKey = identity.smimeKey();
const pass = await AskPopupView.password('S/MIME key', 'OPENPGP/LABEL_SIGN');
const pass = await AskPopupView.password('S/MIME key', 'CRYPTO/SIGN');
params.signPassphrase = pass?.password;
}
}

View file

@ -600,7 +600,7 @@ export class MailMessageView extends AbstractViewRight {
}
/*
if (result?.success) {
i18n('OPENPGP/GOOD_SIGNATURE', {
i18n('CRYPTO/GOOD_SIGNATURE', {
USER: validKey.user + ' (' + validKey.id + ')'
});
message.getText()
@ -610,7 +610,8 @@ export class MailMessageView extends AbstractViewRight {
? keyIds.map(item => item?.toHex?.()).filter(v => v).join(', ')
: '';
i18n('OPENPGP/ERROR', {
i18n('CRYPTO/ERROR', {
TYPE: 'OpenPGP',
ERROR: 'message'
}) + (additional ? ' (' + additional + ')' : '');
}
@ -618,4 +619,25 @@ export class MailMessageView extends AbstractViewRight {
});
}
smimeVerify(/*self, event*/) {
const message = currentMessage();
let data = message.smimeSigned(); // { partId: "1", micAlg: "pgp-sha256" }
if (data) {
data = { ...data }; // clone
data.folder = message.folder;
data.uid = message.uid;
data.bodyPart = data.bodyPart?.raw;
Remote.post('MessageSMimeVerify', null, data).then(response => {
if (response?.Result) {
if (response.Result.body) {
MimeToMessage(response.Result.body, message);
message.html() ? message.viewHtml() : message.viewPlain();
response.Result.body = null;
}
message.smimeVerified(response.Result);
}
});
}
}
}