snappymail/dev/Stores/User/Pgp.js

214 lines
5.5 KiB
JavaScript
Raw Normal View History

import ko from 'ko';
2016-06-30 08:02:45 +08:00
import { isArray, arrayLength, pString, addComputablesTo } from 'Common/Utils';
2016-06-30 08:02:45 +08:00
import { AccountUserStore } from 'Stores/User/Account';
2019-07-05 03:19:24 +08:00
import { showScreenPopup } from 'Knoin/Knoin';
import { MessageOpenPgpPopupView } from 'View/Popup/MessageOpenPgp';
export const PgpUserStore = new class {
constructor() {
this.openpgp = null;
2016-06-30 08:02:45 +08:00
this.openpgpkeys = ko.observableArray();
this.openpgpKeyring = null;
2016-06-30 08:02:45 +08:00
addComputablesTo(this, {
openpgpkeysPublic: () => this.openpgpkeys.filter(item => item && !item.isPrivate),
openpgpkeysPrivate: () => this.openpgpkeys.filter(item => item && item.isPrivate)
});
}
2016-06-30 08:02:45 +08:00
/**
* @returns {boolean}
*/
isSupported() {
return !!this.openpgp;
}
2016-06-30 08:02:45 +08:00
findKeyByHex(keys, hash) {
return keys.find(item => hash && item && (hash === item.id || item.ids.includes(hash)));
}
2016-06-30 08:02:45 +08:00
findPublicKeyByHex(hash) {
return this.findKeyByHex(this.openpgpkeysPublic(), hash);
}
2016-06-30 08:02:45 +08:00
findPrivateKeyByHex(hash) {
return this.findKeyByHex(this.openpgpkeysPrivate(), hash);
}
2016-06-30 08:02:45 +08:00
findPublicKeysByEmail(email) {
return this.openpgpkeysPublic().map(item => {
const key = item && item.emails.includes(email) ? item : null;
return key ? key.getNativeKeys() : [null];
}).flat().filter(v => v);
}
2016-06-30 08:02:45 +08:00
findPublicKeysBySigningKeyIds(signingKeyIds) {
return signingKeyIds.map(id => {
const key = id && id.toHex ? this.findPublicKeyByHex(id.toHex()) : null;
return key ? key.getNativeKeys() : [null];
}).flat().filter(v => v);
}
2016-06-30 08:02:45 +08:00
findPrivateKeysByEncryptionKeyIds(encryptionKeyIds, recipients, returnWrapKeys) {
let result = isArray(encryptionKeyIds)
? encryptionKeyIds.map(id => {
const key = id && id.toHex ? this.findPrivateKeyByHex(id.toHex()) : null;
return key ? (returnWrapKeys ? [key] : key.getNativeKeys()) : [null];
}).flat().filter(v => v)
2019-07-05 03:19:24 +08:00
: [];
2021-07-22 03:34:17 +08:00
if (!result.length && arrayLength(recipients)) {
result = recipients.map(sEmail => {
const keys = sEmail ? this.findAllPrivateKeysByEmailNotNative(sEmail) : null;
return keys
? returnWrapKeys
? keys
: keys.map(key => key.getNativeKeys()).flat()
: [null];
}).flat().validUnique(key => key.id);
}
return result;
2015-02-03 07:58:58 +08:00
}
2015-02-01 23:44:44 +08:00
/**
* @param {string} email
* @returns {?}
*/
findPublicKeyByEmailNotNative(email) {
return this.openpgpkeysPublic().find(item => item && item.emails.includes(email)) || null;
}
2016-06-30 08:02:45 +08:00
/**
* @param {string} email
* @returns {?}
*/
findPrivateKeyByEmailNotNative(email) {
return this.openpgpkeysPrivate().find(item => item && item.emails.includes(email)) || null;
}
/**
* @param {string} email
* @returns {?}
*/
findAllPublicKeysByEmailNotNative(email) {
2020-07-21 03:39:00 +08:00
return this.openpgpkeysPublic().filter(item => item && item.emails.includes(email)) || null;
}
/**
* @param {string} email
* @returns {?}
*/
findAllPrivateKeysByEmailNotNative(email) {
2020-07-21 03:39:00 +08:00
return this.openpgpkeysPrivate().filter(item => item && item.emails.includes(email)) || null;
}
/**
* @param {string} email
* @param {string=} password
* @returns {?}
*/
findPrivateKeyByEmail(email, password) {
let privateKey = null;
const key = this.openpgpkeysPrivate().find(item => item && item.emails.includes(email));
2019-07-05 03:19:24 +08:00
if (key) {
try {
privateKey = key.getNativeKeys()[0] || null;
2019-07-05 03:19:24 +08:00
if (privateKey) {
privateKey.decrypt(pString(password));
}
2019-07-05 03:19:24 +08:00
} catch (e) {
privateKey = null;
2015-02-22 06:00:51 +08:00
}
}
2016-06-30 08:02:45 +08:00
return privateKey;
}
2016-06-30 08:02:45 +08:00
/**
* @param {string=} password
* @returns {?}
*/
findSelfPrivateKey(password) {
return this.findPrivateKeyByEmail(AccountUserStore.email(), password);
}
2016-08-10 02:58:34 +08:00
decryptMessage(message, recipients, fCallback) {
2019-07-05 03:19:24 +08:00
if (message && message.getEncryptionKeyIds) {
const privateKeys = this.findPrivateKeysByEncryptionKeyIds(message.getEncryptionKeyIds(), recipients, true);
if (privateKeys && privateKeys.length) {
showScreenPopup(MessageOpenPgpPopupView, [
2019-07-05 03:19:24 +08:00
(decryptedKey) => {
if (decryptedKey) {
message.decrypt(decryptedKey).then(
(decryptedMessage) => {
let privateKey = null;
if (decryptedMessage) {
privateKey = this.findPrivateKeyByHex(decryptedKey.primaryKey.keyid.toHex());
if (privateKey) {
this.verifyMessage(decryptedMessage, (oValidKey, aSigningKeyIds) => {
fCallback(privateKey, decryptedMessage, oValidKey || null, aSigningKeyIds || null);
});
} else {
fCallback(privateKey, decryptedMessage);
}
} else {
fCallback(privateKey, decryptedMessage);
}
},
() => {
fCallback(null, null);
}
2019-07-05 03:19:24 +08:00
);
} else {
fCallback(null, null);
2019-07-05 03:19:24 +08:00
}
},
privateKeys
]);
return false;
}
}
fCallback(null, null);
return false;
2016-06-30 08:02:45 +08:00
}
2016-05-24 01:33:01 +08:00
verifyMessage(message, fCallback) {
2019-07-05 03:19:24 +08:00
if (message && message.getSigningKeyIds) {
const signingKeyIds = message.getSigningKeyIds();
if (signingKeyIds && signingKeyIds.length) {
const publicKeys = this.findPublicKeysBySigningKeyIds(signingKeyIds);
if (publicKeys && publicKeys.length) {
2019-07-05 03:19:24 +08:00
try {
const result = message.verify(publicKeys),
valid = (isArray(result) ? result : []).find(item => item && item.valid && item.keyid);
2019-07-05 03:19:24 +08:00
if (valid && valid.keyid && valid.keyid && valid.keyid.toHex) {
fCallback(this.findPublicKeyByHex(valid.keyid.toHex()));
return true;
}
2019-07-05 03:19:24 +08:00
} catch (e) {
console.log(e);
2015-10-14 00:36:43 +08:00
}
}
fCallback(null, signingKeyIds);
return false;
}
}
fCallback(null);
return false;
2016-06-30 08:02:45 +08:00
}
};