mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Split OpenPGP.js and GnuPG from PgpUserStore
This commit is contained in:
parent
76226f45ca
commit
76361a13da
6 changed files with 453 additions and 369 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import { PgpUserStore } from 'Stores/User/Pgp';
|
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
||||||
|
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
||||||
import { SettingsUserStore } from 'Stores/User/Settings';
|
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||||
|
|
||||||
import Remote from 'Remote/User/Fetch';
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
@ -13,14 +14,14 @@ import { Settings } from 'Common/Globals';
|
||||||
|
|
||||||
export class OpenPgpUserSettings /*extends AbstractViewSettings*/ {
|
export class OpenPgpUserSettings /*extends AbstractViewSettings*/ {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.gnupgPublicKeys = PgpUserStore.gnupgPublicKeys;
|
this.gnupgPublicKeys = GnuPGUserStore.publicKeys;
|
||||||
this.gnupgPrivateKeys = PgpUserStore.gnupgPrivateKeys;
|
this.gnupgPrivateKeys = GnuPGUserStore.privateKeys;
|
||||||
|
|
||||||
this.openpgpkeysPublic = PgpUserStore.openpgpPublicKeys;
|
this.openpgpkeysPublic = OpenPGPUserStore.publicKeys;
|
||||||
this.openpgpkeysPrivate = PgpUserStore.openpgpPrivateKeys;
|
this.openpgpkeysPrivate = OpenPGPUserStore.privateKeys;
|
||||||
|
|
||||||
this.canOpenPGP = Settings.capa(Capa.OpenPGP);
|
this.canOpenPGP = Settings.capa(Capa.OpenPGP);
|
||||||
this.canGnuPG = Settings.capa(Capa.GnuPG);
|
this.canGnuPG = GnuPGUserStore.isSupported();
|
||||||
this.canMailvelope = !!window.mailvelope;
|
this.canMailvelope = !!window.mailvelope;
|
||||||
|
|
||||||
this.allowDraftAutosave = SettingsUserStore.allowDraftAutosave;
|
this.allowDraftAutosave = SettingsUserStore.allowDraftAutosave;
|
||||||
|
|
|
||||||
154
dev/Stores/User/GnuPG.js
Normal file
154
dev/Stores/User/GnuPG.js
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
import ko from 'ko';
|
||||||
|
|
||||||
|
import { Capa } from 'Common/Enums';
|
||||||
|
import { Settings } from 'Common/Globals';
|
||||||
|
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||||
|
|
||||||
|
//import { showScreenPopup } from 'Knoin/Knoin';
|
||||||
|
|
||||||
|
//import { EmailModel } from 'Model/Email';
|
||||||
|
//import { OpenPgpKeyModel } from 'Model/OpenPgpKey';
|
||||||
|
|
||||||
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
|
import { showScreenPopup } from 'Knoin/Knoin';
|
||||||
|
import { OpenPgpKeyPopupView } from 'View/Popup/OpenPgpKey';
|
||||||
|
|
||||||
|
const
|
||||||
|
findGnuPGKey = (keys, query, sign) =>
|
||||||
|
keys.find(key =>
|
||||||
|
key[sign ? 'can_sign' : 'can_decrypt']
|
||||||
|
&& (key.emails.includes(query) || key.subkeys.find(key => query == key.keyid || query == key.fingerprint))
|
||||||
|
);
|
||||||
|
|
||||||
|
export const GnuPGUserStore = new class {
|
||||||
|
constructor() {
|
||||||
|
/**
|
||||||
|
* PECL gnupg / PEAR Crypt_GPG
|
||||||
|
* [ {email, can_encrypt, can_sign}, ... ]
|
||||||
|
*/
|
||||||
|
this.keyring;
|
||||||
|
this.publicKeys = ko.observableArray();
|
||||||
|
this.privateKeys = ko.observableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadKeyrings(/*identifier*/) {
|
||||||
|
this.keyring = null;
|
||||||
|
this.publicKeys([]);
|
||||||
|
this.privateKeys([]);
|
||||||
|
Remote.request('GnupgGetKeys',
|
||||||
|
(iError, oData) => {
|
||||||
|
if (oData && oData.Result) {
|
||||||
|
this.keyring = oData.Result;
|
||||||
|
const initKey = (key, isPrivate) => {
|
||||||
|
const aEmails = [];
|
||||||
|
key.id = key.subkeys[0].keyid;
|
||||||
|
key.fingerprint = key.subkeys[0].fingerprint;
|
||||||
|
key.uids.forEach(uid => uid.email && aEmails.push(uid.email));
|
||||||
|
key.emails = aEmails;
|
||||||
|
key.askDelete = ko.observable(false);
|
||||||
|
key.openForDeletion = ko.observable(null).askDeleteHelper();
|
||||||
|
key.remove = () => {
|
||||||
|
if (key.askDelete()) {
|
||||||
|
Remote.request('GnupgDeleteKey',
|
||||||
|
(iError, oData) => {
|
||||||
|
if (oData && oData.Result) {
|
||||||
|
if (isPrivate) {
|
||||||
|
this.privateKeys.remove(key);
|
||||||
|
} else {
|
||||||
|
this.publicKeys.remove(key);
|
||||||
|
}
|
||||||
|
delegateRunOnDestroy(key);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
KeyId: key.id,
|
||||||
|
isPrivate: isPrivate
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
key.view = () => {
|
||||||
|
let pass = isPrivate ? prompt('Passphrase') : true;
|
||||||
|
if (pass) {
|
||||||
|
Remote.request('GnupgExportKey',
|
||||||
|
(iError, oData) => {
|
||||||
|
if (oData && oData.Result) {
|
||||||
|
key.armor = oData.Result;
|
||||||
|
showScreenPopup(OpenPgpKeyPopupView, [key]);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
KeyId: key.id,
|
||||||
|
isPrivate: isPrivate,
|
||||||
|
Passphrase: isPrivate ? pass : ''
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return key;
|
||||||
|
};
|
||||||
|
this.publicKeys(oData.Result.public.map(key => initKey(key, 0)));
|
||||||
|
this.privateKeys(oData.Result.private.map(key => initKey(key, 1)));
|
||||||
|
console.log('gnupg ready');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isSupported() {
|
||||||
|
return Settings.capa(Capa.GnuPG);
|
||||||
|
}
|
||||||
|
|
||||||
|
importKey(key, callback) {
|
||||||
|
Remote.request('GnupgImportKey',
|
||||||
|
(iError, oData) => {
|
||||||
|
if (oData && oData.Result) {
|
||||||
|
// this.gnupgKeyring = oData.Result;
|
||||||
|
}
|
||||||
|
callback && callback(iError, oData);
|
||||||
|
}, {
|
||||||
|
Key: key
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
keyPair.privateKey
|
||||||
|
keyPair.publicKey
|
||||||
|
keyPair.revocationCertificate
|
||||||
|
keyPair.onServer
|
||||||
|
keyPair.inGnuPG
|
||||||
|
*/
|
||||||
|
storeKeyPair(keyPair, callback) {
|
||||||
|
Remote.request('PgpStoreKeyPair',
|
||||||
|
(iError, oData) => {
|
||||||
|
if (oData && oData.Result) {
|
||||||
|
// this.gnupgKeyring = oData.Result;
|
||||||
|
}
|
||||||
|
callback && callback(iError, oData);
|
||||||
|
}, keyPair
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if verifying/encrypting a message is possible with given email addresses.
|
||||||
|
*/
|
||||||
|
hasPublicKeyForEmails(recipients, all) {
|
||||||
|
const count = recipients.length,
|
||||||
|
length = count ? recipients.filter(email =>
|
||||||
|
// (key.can_verify || key.can_encrypt) &&
|
||||||
|
this.publicKeys.find(key => key.emails.includes(email))
|
||||||
|
).length : 0;
|
||||||
|
return length && (!all || length === count);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPrivateKeyFor(query, sign) {
|
||||||
|
return findGnuPGKey(this.privateKeys, query, sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPublicKeyFor(query, sign) {
|
||||||
|
return findGnuPGKey(this.publicKeys, query, sign);
|
||||||
|
}
|
||||||
|
};
|
||||||
268
dev/Stores/User/OpenPGP.js
Normal file
268
dev/Stores/User/OpenPGP.js
Normal file
|
|
@ -0,0 +1,268 @@
|
||||||
|
/**
|
||||||
|
* OpenPGP.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ko from 'ko';
|
||||||
|
|
||||||
|
import { isArray, arrayLength } from 'Common/Utils';
|
||||||
|
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||||
|
|
||||||
|
import { showScreenPopup } from 'Knoin/Knoin';
|
||||||
|
import { OpenPgpKeyPopupView } from 'View/Popup/OpenPgpKey';
|
||||||
|
|
||||||
|
const
|
||||||
|
findKeyByHex = (keys, hash) =>
|
||||||
|
keys.find(item => item && (hash === item.id || item.ids.includes(hash))),
|
||||||
|
|
||||||
|
findOpenPGPKey = (keys, query/*, sign*/) =>
|
||||||
|
keys.find(key =>
|
||||||
|
key.emails.includes(query) || query == key.id || query == key.fingerprint
|
||||||
|
),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenPGP.js v5 removed the localStorage (keyring)
|
||||||
|
* This should be compatible with the old OpenPGP.js v2
|
||||||
|
*/
|
||||||
|
publicKeysItem = 'openpgp-public-keys',
|
||||||
|
privateKeysItem = 'openpgp-private-keys',
|
||||||
|
storage = window.localStorage,
|
||||||
|
loadOpenPgpKeys = async itemname => {
|
||||||
|
let keys = [], key,
|
||||||
|
armoredKeys = JSON.parse(storage.getItem(itemname)),
|
||||||
|
i = arrayLength(armoredKeys);
|
||||||
|
while (i--) {
|
||||||
|
key = await openpgp.readKey({armoredKey:armoredKeys[i]});
|
||||||
|
if (!key.err) {
|
||||||
|
keys.push(new OpenPgpKeyModel(armoredKeys[i], key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
},
|
||||||
|
storeOpenPgpKeys = (keys, section) => {
|
||||||
|
let armoredKeys = keys.map(item => item.armor);
|
||||||
|
if (armoredKeys.length) {
|
||||||
|
storage.setItem(section, JSON.stringify(armoredKeys));
|
||||||
|
} else {
|
||||||
|
storage.removeItem(section);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenPgpKeyModel {
|
||||||
|
constructor(armor, key) {
|
||||||
|
this.key = key;
|
||||||
|
const aEmails = [];
|
||||||
|
if (key.users) {
|
||||||
|
key.users.forEach(user => user.userID.email && aEmails.push(user.userID.email));
|
||||||
|
}
|
||||||
|
this.id = key.getKeyID().toHex();
|
||||||
|
this.fingerprint = key.getFingerprint();
|
||||||
|
this.can_encrypt = !!key.getEncryptionKey();
|
||||||
|
this.can_sign = !!key.getSigningKey();
|
||||||
|
this.emails = aEmails;
|
||||||
|
this.armor = armor;
|
||||||
|
this.askDelete = ko.observable(false);
|
||||||
|
this.openForDeletion = ko.observable(null).askDeleteHelper();
|
||||||
|
// key.getUserIDs()
|
||||||
|
// key.getPrimaryUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
view() {
|
||||||
|
showScreenPopup(OpenPgpKeyPopupView, [this]);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
if (this.askDelete()) {
|
||||||
|
if (this.key.isPrivate()) {
|
||||||
|
OpenPGPUserStore.privateKeys.remove(this);
|
||||||
|
storeOpenPgpKeys(OpenPGPUserStore.privateKeys, privateKeysItem);
|
||||||
|
} else {
|
||||||
|
OpenPGPUserStore.publicKeys.remove(this);
|
||||||
|
storeOpenPgpKeys(OpenPGPUserStore.publicKeys, publicKeysItem);
|
||||||
|
}
|
||||||
|
delegateRunOnDestroy(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
toJSON() {
|
||||||
|
return this.armor;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OpenPGPUserStore = new class {
|
||||||
|
constructor() {
|
||||||
|
this.publicKeys = ko.observableArray();
|
||||||
|
this.privateKeys = ko.observableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadKeyrings() {
|
||||||
|
loadOpenPgpKeys(publicKeysItem).then(keys => {
|
||||||
|
this.publicKeys(keys || []);
|
||||||
|
console.log('openpgp.js public keys loaded');
|
||||||
|
});
|
||||||
|
loadOpenPgpKeys(privateKeysItem).then(keys => {
|
||||||
|
this.privateKeys(keys || [])
|
||||||
|
console.log('openpgp.js private keys loaded');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isSupported() {
|
||||||
|
return !!window.openpgp;
|
||||||
|
}
|
||||||
|
|
||||||
|
importKey(armoredKey) {
|
||||||
|
openpgp.readKey({armoredKey:armoredKey}).then(key => {
|
||||||
|
if (!key.err) {
|
||||||
|
if (key.isPrivate()) {
|
||||||
|
this.privateKeys.push(new OpenPgpKeyModel(armoredKey, key));
|
||||||
|
storeOpenPgpKeys(this.privateKeys, privateKeysItem);
|
||||||
|
} else {
|
||||||
|
this.publicKeys.push(new OpenPgpKeyModel(armoredKey, key));
|
||||||
|
storeOpenPgpKeys(this.publicKeys, publicKeysItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
keyPair.privateKey
|
||||||
|
keyPair.publicKey
|
||||||
|
keyPair.revocationCertificate
|
||||||
|
keyPair.onServer
|
||||||
|
keyPair.inGnuPG
|
||||||
|
*/
|
||||||
|
storeKeyPair(keyPair) {
|
||||||
|
openpgp.readKey({armoredKey:keyPair.publicKey}).then(key => {
|
||||||
|
this.publicKeys.push(new OpenPgpKeyModel(keyPair.publicKey, key));
|
||||||
|
storeOpenPgpKeys(this.publicKeys, publicKeysItem);
|
||||||
|
});
|
||||||
|
openpgp.readKey({armoredKey:keyPair.privateKey}).then(key => {
|
||||||
|
this.privateKeys.push(new OpenPgpKeyModel(keyPair.privateKey, key));
|
||||||
|
storeOpenPgpKeys(this.privateKeys, privateKeysItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if verifying/encrypting a message is possible with given email addresses.
|
||||||
|
*/
|
||||||
|
hasPublicKeyForEmails(recipients, all) {
|
||||||
|
const count = recipients.length,
|
||||||
|
length = count ? recipients.filter(email =>
|
||||||
|
this.publicKeys().find(key => key.emails.includes(email))
|
||||||
|
).length : 0;
|
||||||
|
return length && (!all || length === count);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPrivateKeyFor(query/*, sign*/) {
|
||||||
|
return findOpenPGPKey(this.privateKeys, query/*, sign*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPublicKeyFor(query/*, sign*/) {
|
||||||
|
return findOpenPGPKey(this.publicKeys, query/*, sign*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
decryptMessage(message, recipients, fCallback) {
|
||||||
|
message = store.openpgp.message.readArmored(armoredMessage);
|
||||||
|
try {
|
||||||
|
message = store.openpgp.message.readArmored(armoredMessage);
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
|
if (message && message.getText && message.verify && message.decrypt) {
|
||||||
|
if (message && message.getEncryptionKeyIds) {
|
||||||
|
// findPrivateKeysByEncryptionKeyIds
|
||||||
|
const encryptionKeyIds = message.getEncryptionKeyIds();
|
||||||
|
let privateKeys = isArray(encryptionKeyIds)
|
||||||
|
? encryptionKeyIds.map(id => {
|
||||||
|
// openpgpKeyring.publicKeys.getForId(id.toHex())
|
||||||
|
// openpgpKeyring.privateKeys.getForId(id.toHex())
|
||||||
|
const key = id && id.toHex ? findKeyByHex(this.privateKeys, id.toHex()) : null;
|
||||||
|
return key ? [key] : [null];
|
||||||
|
}).flat().filter(v => v)
|
||||||
|
: [];
|
||||||
|
if (!privateKeys.length && arrayLength(recipients)) {
|
||||||
|
privateKeys = recipients.map(sEmail =>
|
||||||
|
(sEmail
|
||||||
|
? this.privateKeys.filter(item => item && item.emails.includes(sEmail)) : 0)
|
||||||
|
|| [null]
|
||||||
|
).flat().validUnique(key => key.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (privateKeys && privateKeys.length) {
|
||||||
|
showScreenPopup(OpenPgpSelectorPopupView, [
|
||||||
|
(decryptedKey) => {
|
||||||
|
if (decryptedKey) {
|
||||||
|
message.decrypt(decryptedKey).then(
|
||||||
|
(decryptedMessage) => {
|
||||||
|
let privateKey = null;
|
||||||
|
if (decryptedMessage) {
|
||||||
|
privateKey = findKeyByHex(this.privateKeys, 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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
fCallback(null, null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
privateKeys
|
||||||
|
]);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fCallback(null, null);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
verifyMessage(message, fCallback) {
|
||||||
|
if (message && message.getSigningKeyIds) {
|
||||||
|
const signingKeyIds = message.getSigningKeyIds();
|
||||||
|
if (signingKeyIds && signingKeyIds.length) {
|
||||||
|
// findPublicKeysBySigningKeyIds
|
||||||
|
const publicKeys = signingKeyIds.map(id => {
|
||||||
|
const key = id && id.toHex ? findKeyByHex(this.publicKeys, id.toHex()) : null;
|
||||||
|
return key ? key.key : [null];
|
||||||
|
}).flat().filter(v => v);
|
||||||
|
if (publicKeys && publicKeys.length) {
|
||||||
|
try {
|
||||||
|
const result = message.verify(publicKeys),
|
||||||
|
valid = (isArray(result) ? result : []).find(item => item && item.valid && item.keyid);
|
||||||
|
|
||||||
|
if (valid && valid.keyid && valid.keyid && valid.keyid.toHex) {
|
||||||
|
fCallback(findKeyByHex(this.publicKeys, valid.keyid.toHex()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fCallback(null, signingKeyIds);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fCallback(null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -1,121 +1,17 @@
|
||||||
import ko from 'ko';
|
|
||||||
|
|
||||||
import { Capa } from 'Common/Enums';
|
import { Capa } from 'Common/Enums';
|
||||||
import { doc, createElement, Settings } from 'Common/Globals';
|
import { doc, createElement, Settings } from 'Common/Globals';
|
||||||
import { staticLink } from 'Common/Links';
|
import { staticLink } from 'Common/Links';
|
||||||
import { isArray, arrayLength } from 'Common/Utils';
|
|
||||||
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
|
||||||
|
|
||||||
//import { showScreenPopup } from 'Knoin/Knoin';
|
//import { showScreenPopup } from 'Knoin/Knoin';
|
||||||
|
|
||||||
//import { EmailModel } from 'Model/Email';
|
//import { EmailModel } from 'Model/Email';
|
||||||
//import { OpenPgpKeyModel } from 'Model/OpenPgpKey';
|
//import { OpenPgpKeyModel } from 'Model/OpenPgpKey';
|
||||||
|
|
||||||
import Remote from 'Remote/User/Fetch';
|
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
||||||
|
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
||||||
import { showScreenPopup } from 'Knoin/Knoin';
|
|
||||||
import { OpenPgpKeyPopupView } from 'View/Popup/OpenPgpKey';
|
|
||||||
|
|
||||||
const
|
|
||||||
findKeyByHex = (keys, hash) =>
|
|
||||||
keys.find(item => item && (hash === item.id || item.ids.includes(hash))),
|
|
||||||
|
|
||||||
findGnuPGKey = (keys, query, sign) =>
|
|
||||||
keys.find(key =>
|
|
||||||
key[sign ? 'can_sign' : 'can_decrypt']
|
|
||||||
&& (key.emails.includes(query) || key.subkeys.find(key => query == key.keyid || query == key.fingerprint))
|
|
||||||
),
|
|
||||||
|
|
||||||
findOpenPGPKey = (keys, query/*, sign*/) =>
|
|
||||||
keys.find(key =>
|
|
||||||
key.emails.includes(query) || query == key.id || query == key.fingerprint
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OpenPGP.js v5 removed the localStorage (keyring)
|
|
||||||
* This should be compatible with the old OpenPGP.js v2
|
|
||||||
*/
|
|
||||||
const
|
|
||||||
publicKeysItem = 'openpgp-public-keys',
|
|
||||||
privateKeysItem = 'openpgp-private-keys',
|
|
||||||
storage = window.localStorage,
|
|
||||||
loadOpenPgpKeys = async itemname => {
|
|
||||||
let keys = [], key,
|
|
||||||
armoredKeys = JSON.parse(storage.getItem(itemname)),
|
|
||||||
i = arrayLength(armoredKeys);
|
|
||||||
while (i--) {
|
|
||||||
key = await openpgp.readKey({armoredKey:armoredKeys[i]});
|
|
||||||
if (!key.err) {
|
|
||||||
keys.push(new OpenPgpKeyModel(armoredKeys[i], key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
},
|
|
||||||
storeOpenPgpKeys = (keys, section) => {
|
|
||||||
let armoredKeys = keys.map(item => item.armor);
|
|
||||||
if (armoredKeys.length) {
|
|
||||||
storage.setItem(section, JSON.stringify(armoredKeys));
|
|
||||||
} else {
|
|
||||||
storage.removeItem(section);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class OpenPgpKeyModel {
|
|
||||||
constructor(armor, key) {
|
|
||||||
this.key = key;
|
|
||||||
const aEmails = [];
|
|
||||||
if (key.users) {
|
|
||||||
key.users.forEach(user => user.userID.email && aEmails.push(user.userID.email));
|
|
||||||
}
|
|
||||||
this.id = key.getKeyID().toHex();
|
|
||||||
this.fingerprint = key.getFingerprint();
|
|
||||||
this.can_encrypt = !!key.getEncryptionKey();
|
|
||||||
this.can_sign = !!key.getSigningKey();
|
|
||||||
this.emails = aEmails;
|
|
||||||
this.armor = armor;
|
|
||||||
this.askDelete = ko.observable(false);
|
|
||||||
this.openForDeletion = ko.observable(null).askDeleteHelper();
|
|
||||||
// key.getUserIDs()
|
|
||||||
// key.getPrimaryUser()
|
|
||||||
}
|
|
||||||
|
|
||||||
view() {
|
|
||||||
showScreenPopup(OpenPgpKeyPopupView, [this]);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove() {
|
|
||||||
if (this.askDelete()) {
|
|
||||||
if (this.key.isPrivate()) {
|
|
||||||
PgpUserStore.openpgpPrivateKeys.remove(this);
|
|
||||||
storeOpenPgpKeys(PgpUserStore.openpgpPrivateKeys, privateKeysItem);
|
|
||||||
} else {
|
|
||||||
PgpUserStore.openpgpPublicKeys.remove(this);
|
|
||||||
storeOpenPgpKeys(PgpUserStore.openpgpPublicKeys, publicKeysItem);
|
|
||||||
}
|
|
||||||
delegateRunOnDestroy(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
toJSON() {
|
|
||||||
return this.armor;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PgpUserStore = new class {
|
export const PgpUserStore = new class {
|
||||||
constructor() {
|
constructor() {
|
||||||
/**
|
|
||||||
* PECL gnupg / PEAR Crypt_GPG
|
|
||||||
* [ {email, can_encrypt, can_sign}, ... ]
|
|
||||||
*/
|
|
||||||
this.gnupgKeyring;
|
|
||||||
this.gnupgPublicKeys = ko.observableArray();
|
|
||||||
this.gnupgPrivateKeys = ko.observableArray();
|
|
||||||
|
|
||||||
// OpenPGP.js
|
|
||||||
this.openpgpPublicKeys = ko.observableArray();
|
|
||||||
this.openpgpPrivateKeys = ko.observableArray();
|
|
||||||
|
|
||||||
// https://mailvelope.github.io/mailvelope/Keyring.html
|
// https://mailvelope.github.io/mailvelope/Keyring.html
|
||||||
this.mailvelopeKeyring = null;
|
this.mailvelopeKeyring = null;
|
||||||
}
|
}
|
||||||
|
|
@ -155,77 +51,12 @@ export const PgpUserStore = new class {
|
||||||
addEventListener('mailvelope', () => this.loadKeyrings(identifier));
|
addEventListener('mailvelope', () => this.loadKeyrings(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openpgp) {
|
if (OpenPGPUserStore.isSupported()) {
|
||||||
loadOpenPgpKeys(publicKeysItem).then(keys => {
|
OpenPGPUserStore.loadKeyrings(identifier);
|
||||||
this.openpgpPublicKeys(keys || []);
|
|
||||||
console.log('openpgp.js public keys loaded');
|
|
||||||
});
|
|
||||||
loadOpenPgpKeys(privateKeysItem).then(keys => {
|
|
||||||
this.openpgpPrivateKeys(keys || [])
|
|
||||||
console.log('openpgp.js private keys loaded');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.capa(Capa.GnuPG)) {
|
if (Settings.capa(Capa.GnuPG)) {
|
||||||
this.gnupgKeyring = null;
|
GnuPGUserStore.loadKeyrings(identifier);
|
||||||
this.gnupgPublicKeys([]);
|
|
||||||
this.gnupgPrivateKeys([]);
|
|
||||||
Remote.request('GnupgGetKeys',
|
|
||||||
(iError, oData) => {
|
|
||||||
if (oData && oData.Result) {
|
|
||||||
this.gnupgKeyring = oData.Result;
|
|
||||||
const initKey = (key, isPrivate) => {
|
|
||||||
const aEmails = [];
|
|
||||||
key.id = key.subkeys[0].keyid;
|
|
||||||
key.fingerprint = key.subkeys[0].fingerprint;
|
|
||||||
key.uids.forEach(uid => uid.email && aEmails.push(uid.email));
|
|
||||||
key.emails = aEmails;
|
|
||||||
key.askDelete = ko.observable(false);
|
|
||||||
key.openForDeletion = ko.observable(null).askDeleteHelper();
|
|
||||||
key.remove = () => {
|
|
||||||
if (key.askDelete()) {
|
|
||||||
Remote.request('GnupgDeleteKey',
|
|
||||||
(iError, oData) => {
|
|
||||||
if (oData && oData.Result) {
|
|
||||||
if (isPrivate) {
|
|
||||||
PgpUserStore.gnupgPrivateKeys.remove(key);
|
|
||||||
} else {
|
|
||||||
PgpUserStore.gnupgPublicKeys.remove(key);
|
|
||||||
}
|
|
||||||
delegateRunOnDestroy(key);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
KeyId: key.id,
|
|
||||||
isPrivate: isPrivate
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
key.view = () => {
|
|
||||||
let pass = isPrivate ? prompt('Passphrase') : true;
|
|
||||||
if (pass) {
|
|
||||||
Remote.request('GnupgExportKey',
|
|
||||||
(iError, oData) => {
|
|
||||||
if (oData && oData.Result) {
|
|
||||||
key.armor = oData.Result;
|
|
||||||
showScreenPopup(OpenPgpKeyPopupView, [key]);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
KeyId: key.id,
|
|
||||||
isPrivate: isPrivate,
|
|
||||||
Passphrase: isPrivate ? pass : ''
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return key;
|
|
||||||
};
|
|
||||||
this.gnupgPublicKeys(oData.Result.public.map(key => initKey(key, 0)));
|
|
||||||
this.gnupgPrivateKeys(oData.Result.private.map(key => initKey(key, 1)));
|
|
||||||
console.log('gnupg ready');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,36 +64,7 @@ export const PgpUserStore = new class {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isSupported() {
|
isSupported() {
|
||||||
return !!(window.openpgp || window.mailvelope || Settings.capa(Capa.GnuPG));
|
return !!(OpenPGPUserStore.isSupported() || GnuPGUserStore.isSupported() || window.mailvelope);
|
||||||
}
|
|
||||||
|
|
||||||
openpgpImportKey(armoredKey) {
|
|
||||||
openpgp && openpgp.readKey({armoredKey:armoredKey}).then(key => {
|
|
||||||
if (!key.err) {
|
|
||||||
if (key.isPrivate()) {
|
|
||||||
this.openpgpPrivateKeys.push(new OpenPgpKeyModel(armoredKey, key));
|
|
||||||
storeOpenPgpKeys(this.openpgpPrivateKeys, privateKeysItem);
|
|
||||||
} else {
|
|
||||||
this.openpgpPublicKeys.push(new OpenPgpKeyModel(armoredKey, key));
|
|
||||||
storeOpenPgpKeys(PgpUserStore.openpgpPublicKeys, publicKeysItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
gnupgImportKey(key, callback) {
|
|
||||||
if (Settings.capa(Capa.GnuPG)) {
|
|
||||||
Remote.request('GnupgImportKey',
|
|
||||||
(iError, oData) => {
|
|
||||||
if (oData && oData.Result) {
|
|
||||||
// this.gnupgKeyring = oData.Result;
|
|
||||||
}
|
|
||||||
callback && callback(iError, oData);
|
|
||||||
}, {
|
|
||||||
Key: key
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -273,23 +75,9 @@ export const PgpUserStore = new class {
|
||||||
keyPair.inGnuPG
|
keyPair.inGnuPG
|
||||||
*/
|
*/
|
||||||
storeKeyPair(keyPair, callback) {
|
storeKeyPair(keyPair, callback) {
|
||||||
openpgp.readKey({armoredKey:keyPair.publicKey}).then(key => {
|
OpenPGPUserStore.isSupported() && OpenPGPUserStore.storeKeyPair(keyPair);
|
||||||
PgpUserStore.openpgpPublicKeys.push(new OpenPgpKeyModel(keyPair.publicKey, key));
|
|
||||||
storeOpenPgpKeys(PgpUserStore.openpgpPublicKeys, publicKeysItem);
|
|
||||||
});
|
|
||||||
openpgp.readKey({armoredKey:keyPair.privateKey}).then(key => {
|
|
||||||
PgpUserStore.openpgpPrivateKeys.push(new OpenPgpKeyModel(keyPair.privateKey, key));
|
|
||||||
storeOpenPgpKeys(PgpUserStore.openpgpPrivateKeys, privateKeysItem);
|
|
||||||
});
|
|
||||||
// if (Settings.capa(Capa.GnuPG)) {
|
// if (Settings.capa(Capa.GnuPG)) {
|
||||||
Remote.request('PgpStoreKeyPair',
|
GnuPGUserStore.storeKeyPair(keyPair, callback);
|
||||||
(iError, oData) => {
|
|
||||||
if (oData && oData.Result) {
|
|
||||||
// this.gnupgKeyring = oData.Result;
|
|
||||||
}
|
|
||||||
callback && callback(iError, oData);
|
|
||||||
}, keyPair
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -299,18 +87,11 @@ export const PgpUserStore = new class {
|
||||||
async hasPublicKeyForEmails(recipients, all) {
|
async hasPublicKeyForEmails(recipients, all) {
|
||||||
const count = recipients.length;
|
const count = recipients.length;
|
||||||
if (count) {
|
if (count) {
|
||||||
let length = this.gnupgKeyring && recipients.filter(email =>
|
if (GnuPGUserStore.hasPublicKeyForEmails(recipients, all)) {
|
||||||
// (key.can_verify || key.can_encrypt) &&
|
|
||||||
this.gnupgPublicKeys.find(key => key.emails.includes(email))
|
|
||||||
).length;
|
|
||||||
if (length && (!all || length === count)) {
|
|
||||||
return 'gnupg';
|
return 'gnupg';
|
||||||
}
|
}
|
||||||
|
|
||||||
length = recipients.filter(email =>
|
if (OpenPGPUserStore.hasPublicKeyForEmails(recipients, all)) {
|
||||||
this.openpgpPublicKeys().find(key => key.emails.includes(email))
|
|
||||||
).length;
|
|
||||||
if (openpgp && (!all || openpgp === count)) {
|
|
||||||
return 'openpgp';
|
return 'openpgp';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,28 +107,14 @@ export const PgpUserStore = new class {
|
||||||
}
|
}
|
||||||
|
|
||||||
getGnuPGPrivateKeyFor(query, sign) {
|
getGnuPGPrivateKeyFor(query, sign) {
|
||||||
let key = findGnuPGKey(this.gnupgPrivateKeys, query, sign);
|
let key = GnuPGUserStore.getPrivateKeyFor(query, sign);
|
||||||
if (key) {
|
|
||||||
return ['gnupg', key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getGnuPGPublicKeyFor(query, sign) {
|
|
||||||
let key = findGnuPGKey(this.gnupgPublicKeys, query, sign);
|
|
||||||
if (key) {
|
if (key) {
|
||||||
return ['gnupg', key];
|
return ['gnupg', key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getOpenPGPPrivateKeyFor(query/*, sign*/) {
|
getOpenPGPPrivateKeyFor(query/*, sign*/) {
|
||||||
let key = findOpenPGPKey(this.openpgpPrivateKeys, query/*, sign*/);
|
let key = OpenPGPUserStore.getPrivateKeyFor(query/*, sign*/);
|
||||||
if (key) {
|
|
||||||
return ['openpgp', key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getOpenPGPPublicKeyFor(query/*, sign*/) {
|
|
||||||
let key = findOpenPGPKey(this.openpgpPublicKeys, query/*, sign*/);
|
|
||||||
if (key) {
|
if (key) {
|
||||||
return ['openpgp', key];
|
return ['openpgp', key];
|
||||||
}
|
}
|
||||||
|
|
@ -400,6 +167,7 @@ export const PgpUserStore = new class {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = ids.length;
|
i = ids.length;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
key = this.getOpenPGPPrivateKeyFor(ids[i]);
|
key = this.getOpenPGPPrivateKeyFor(ids[i]);
|
||||||
|
|
@ -409,104 +177,6 @@ export const PgpUserStore = new class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* OpenPGP.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
decryptMessage(message, recipients, fCallback) {
|
|
||||||
if (message && message.getEncryptionKeyIds) {
|
|
||||||
// findPrivateKeysByEncryptionKeyIds
|
|
||||||
const encryptionKeyIds = message.getEncryptionKeyIds();
|
|
||||||
let privateKeys = isArray(encryptionKeyIds)
|
|
||||||
? encryptionKeyIds.map(id => {
|
|
||||||
// openpgpKeyring.publicKeys.getForId(id.toHex())
|
|
||||||
// openpgpKeyring.privateKeys.getForId(id.toHex())
|
|
||||||
const key = id && id.toHex ? findKeyByHex(this.openpgpPrivateKeys, id.toHex()) : null;
|
|
||||||
return key ? [key] : [null];
|
|
||||||
}).flat().filter(v => v)
|
|
||||||
: [];
|
|
||||||
if (!privateKeys.length && arrayLength(recipients)) {
|
|
||||||
privateKeys = recipients.map(sEmail =>
|
|
||||||
(sEmail
|
|
||||||
? this.openpgpPrivateKeys.filter(item => item && item.emails.includes(sEmail)) : 0)
|
|
||||||
|| [null]
|
|
||||||
).flat().validUnique(key => key.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (privateKeys && privateKeys.length) {
|
|
||||||
showScreenPopup(OpenPgpSelectorPopupView, [
|
|
||||||
(decryptedKey) => {
|
|
||||||
if (decryptedKey) {
|
|
||||||
message.decrypt(decryptedKey).then(
|
|
||||||
(decryptedMessage) => {
|
|
||||||
let privateKey = null;
|
|
||||||
if (decryptedMessage) {
|
|
||||||
privateKey = findKeyByHex(this.openpgpPrivateKeys, 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);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
fCallback(null, null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
privateKeys
|
|
||||||
]);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fCallback(null, null);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
verifyMessage(message, fCallback) {
|
|
||||||
if (message && message.getSigningKeyIds) {
|
|
||||||
const signingKeyIds = message.getSigningKeyIds();
|
|
||||||
if (signingKeyIds && signingKeyIds.length) {
|
|
||||||
// findPublicKeysBySigningKeyIds
|
|
||||||
const publicKeys = signingKeyIds.map(id => {
|
|
||||||
const key = id && id.toHex ? findKeyByHex(this.openpgpPublicKeys, id.toHex()) : null;
|
|
||||||
return key ? key.key : [null];
|
|
||||||
}).flat().filter(v => v);
|
|
||||||
if (publicKeys && publicKeys.length) {
|
|
||||||
try {
|
|
||||||
const result = message.verify(publicKeys),
|
|
||||||
valid = (isArray(result) ? result : []).find(item => item && item.valid && item.keyid);
|
|
||||||
|
|
||||||
if (valid && valid.keyid && valid.keyid && valid.keyid.toHex) {
|
|
||||||
fCallback(findKeyByHex(this.openpgpPublicKeys, valid.keyid.toHex()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fCallback(null, signingKeyIds);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fCallback(null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an iframe with an editor for a new encrypted mail.
|
* Creates an iframe with an editor for a new encrypted mail.
|
||||||
* The iframe will be injected into the container identified by selector.
|
* The iframe will be injected into the container identified by selector.
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import { IdentityUserStore } from 'Stores/User/Identity';
|
||||||
import { AccountUserStore } from 'Stores/User/Account';
|
import { AccountUserStore } from 'Stores/User/Account';
|
||||||
import { FolderUserStore } from 'Stores/User/Folder';
|
import { FolderUserStore } from 'Stores/User/Folder';
|
||||||
import { PgpUserStore } from 'Stores/User/Pgp';
|
import { PgpUserStore } from 'Stores/User/Pgp';
|
||||||
|
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
||||||
import { MessageUserStore } from 'Stores/User/Message';
|
import { MessageUserStore } from 'Stores/User/Message';
|
||||||
|
|
||||||
import Remote from 'Remote/User/Fetch';
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
@ -458,10 +459,10 @@ class ComposePopupView extends AbstractViewPopup {
|
||||||
if ('openpgp' == sign) {
|
if ('openpgp' == sign) {
|
||||||
let privateKey;
|
let privateKey;
|
||||||
try {
|
try {
|
||||||
const keys = PgpUserStore.getOpenPGPPrivateKeyFor(this.currentIdentity().email());
|
const key = OpenPGPUserStore.getPrivateKeyFor(this.currentIdentity().email());
|
||||||
if (keys[0]) {
|
if (key) {
|
||||||
keys[0].decrypt(window.prompt('Passphrase'));
|
key.decrypt(window.prompt('Passphrase'));
|
||||||
cfg.privateKey = privateKey = keys[0];
|
cfg.privateKey = privateKey = key;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
@ -477,7 +478,7 @@ class ComposePopupView extends AbstractViewPopup {
|
||||||
// error 'sign and encrypt must be same engine';
|
// error 'sign and encrypt must be same engine';
|
||||||
} else if ('openpgp' == encrypt) {
|
} else if ('openpgp' == encrypt) {
|
||||||
this.allRecipients().forEach(recEmail => {
|
this.allRecipients().forEach(recEmail => {
|
||||||
cfg.publicKeys = cfg.publicKeys.concat(PgpUserStore.getOpenPGPPublicKeyFor(recEmail));
|
cfg.publicKeys = cfg.publicKeys.concat(OpenPGPUserStore.getPublicKeyFor(recEmail));
|
||||||
});
|
});
|
||||||
pgpPromise = openpgp.encrypt(cfg);
|
pgpPromise = openpgp.encrypt(cfg);
|
||||||
} else if ('openpgp' == sign) {
|
} else if ('openpgp' == sign) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import { PgpUserStore } from 'Stores/User/Pgp';
|
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
||||||
|
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
||||||
|
|
||||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||||
|
|
||||||
import { Capa } from 'Common/Enums';
|
|
||||||
import { Settings } from 'Common/Globals';
|
|
||||||
|
|
||||||
export class OpenPgpImportPopupView extends AbstractViewPopup {
|
export class OpenPgpImportPopupView extends AbstractViewPopup {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('OpenPgpImport');
|
super('OpenPgpImport');
|
||||||
|
|
@ -18,7 +16,7 @@ export class OpenPgpImportPopupView extends AbstractViewPopup {
|
||||||
saveServer: true
|
saveServer: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this.canGnuPG = Settings.capa(Capa.GnuPG);
|
this.canGnuPG = GnuPGUserStore.isSupported();
|
||||||
|
|
||||||
this.key.subscribe(() => {
|
this.key.subscribe(() => {
|
||||||
this.keyError(false);
|
this.keyError(false);
|
||||||
|
|
@ -50,16 +48,8 @@ export class OpenPgpImportPopupView extends AbstractViewPopup {
|
||||||
match = reg.exec(keyTrimmed);
|
match = reg.exec(keyTrimmed);
|
||||||
if (match && 0 < count) {
|
if (match && 0 < count) {
|
||||||
if (match[0] && match[1] && match[2] && match[1] === match[2]) {
|
if (match[0] && match[1] && match[2] && match[1] === match[2]) {
|
||||||
let err = null;
|
this.saveGnuPG() && GnuPGUserStore.isSupported() && GnuPGUserStore.importKey(this.key());
|
||||||
if (this.saveGnuPG()) {
|
OpenPGPUserStore.isSupported() && OpenPGPUserStore.importKey(this.key());
|
||||||
PgpUserStore.gnupgImportKey(this.key());
|
|
||||||
}
|
|
||||||
PgpUserStore.openpgpImportKey(this.key());
|
|
||||||
if (err) {
|
|
||||||
this.keyError(true);
|
|
||||||
this.keyErrorMessage(err && err[0] ? '' + err[0] : '');
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--count;
|
--count;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue