diff --git a/README.md b/README.md index 307bf62d2..a6fff690f 100644 --- a/README.md +++ b/README.md @@ -158,11 +158,6 @@ RainLoop 1.15 vs SnappyMail For a user its around 70% smaller and faster than traditional RainLoop. -|OpenPGP |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli | -|--------------- |--------: |--------: |------: |------: |--------: |--------: | -|openpgp.min.js | 330.742 | 293.972 |102.388 | 93.030 | 84.241 | 77.142 | -|openpgp.worker | 1.499 | 1.125 | 824 | 567 | 695 | 467 | - ### CSS changes * Solve jQuery removed "features" with native css code @@ -178,13 +173,7 @@ For a user its around 70% smaller and faster than traditional RainLoop. * Removed Internet Explorer from normalize.css * Removed node_modules/opentip/css/opentip.css * Removed node_modules/pikaday/css/pikaday.css -* Removed vendors/bootstrap/less/breadcrumbs.less -* Removed vendors/bootstrap/less/navbar.less -* Removed vendors/bootstrap/less/popovers.less -* Removed vendors/bootstrap/less/progress-bars.less -* Removed vendors/bootstrap/less/scaffolding.less -* Removed vendors/bootstrap/less/sprites.less -* Removed vendors/bootstrap/less/tooltip.less +* Removed unused vendors/bootstrap/less/* * Removed vendors/jquery-nanoscroller/nanoscroller.css * Removed vendors/jquery-letterfx/jquery-letterfx.min.css * Removed vendors/Progress.js/minified/progressjs.min.css @@ -200,6 +189,16 @@ For a user its around 70% smaller and faster than traditional RainLoop. |admin.css | | 30.558 | | 6.894 | 5.979 | |admin.min.css | | 24.546 | | 6.241 | 5.489 | +### PGP +RainLoop uses the old OpenPGP.js v2 +SnappyMail v2.12 uses OpenPGP.js v5, GnuPG and Mailvelope. +SnappyMail is able to use and generate ECDSA and EDDSA keys, where RainLoop does not. + +|OpenPGP |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli | +|--------------- |--------: |--------: |------: |-------: |--------: |--------: | +|openpgp.min.js | 330.742 | 550.724 |102.388 | 170.033 | 84.241 | 139.429 | +|openpgp.worker | 1.499 | | 824 | | 695 | | + ### Squire vs CKEditor The [Squire](https://github.com/neilj/Squire) implementation is not 100% compatible yet, but it shows the massive overhead of CKEditor. diff --git a/dev/Model/OpenPgpKey.js b/dev/Model/OpenPgpKey.js deleted file mode 100644 index 665f7e6d2..000000000 --- a/dev/Model/OpenPgpKey.js +++ /dev/null @@ -1,53 +0,0 @@ -import ko from 'ko'; - -import { arrayLength } from 'Common/Utils'; -import { AbstractModel } from 'Knoin/AbstractModel'; - -export class OpenPgpKeyModel extends AbstractModel { - /** - * @param {string} guID - * @param {string} ID - * @param {array} IDs - * @param {array} userIDs - * @param {array} emails - * @param {string} armor - * @param {string} userID - */ - constructor(guID, ID, IDs, userIDs, emails, armor, userID) { - super(); - - this.id = ID; - this.ids = arrayLength(IDs) ? IDs : [ID]; - this.guid = guID; - this.user = ''; - this.users = userIDs; - this.email = ''; - this.emails = emails; - this.armor = armor; - - if (this.users) { - const index = this.users.indexOf(userID); - if (-1 !== index) { - this.user = this.users[index]; - this.email = this.emails[index]; - } - } - - this.deleteAccess = ko.observable(false); - } - - /** - * OpenPGP.js - */ - getNativeKeys() { - try { - let key = openpgp.key.readArmored(this.armor); - if (key && !key.err && key.keys && key.keys[0]) { - return key.keys; - } - } catch (e) { - console.error(e); - } - return null; - } -} diff --git a/dev/Settings/User/OpenPgp.js b/dev/Settings/User/OpenPgp.js index 1685ca8d6..f4d490113 100644 --- a/dev/Settings/User/OpenPgp.js +++ b/dev/Settings/User/OpenPgp.js @@ -9,7 +9,6 @@ import { showScreenPopup } from 'Knoin/Knoin'; import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport'; import { OpenPgpGeneratePopupView } from 'View/Popup/OpenPgpGenerate'; -import { ViewOpenPgpKeyPopupView } from 'View/Popup/ViewOpenPgpKey'; import { Capa } from 'Common/Enums'; import { Settings } from 'Common/Globals'; @@ -39,12 +38,6 @@ export class OpenPgpUserSettings /*extends AbstractViewSettings*/ { showScreenPopup(OpenPgpGeneratePopupView); } - viewOpenPgpKey(openPgpKey) { - if (openPgpKey) { - showScreenPopup(ViewOpenPgpKeyPopupView, [openPgpKey]); - } - } - onBuild() { /** * Create an iframe to display the Mailvelope keyring settings. @@ -52,15 +45,4 @@ export class OpenPgpUserSettings /*extends AbstractViewSettings*/ { */ window.mailvelope && mailvelope.createSettingsContainer('#mailvelope-settings'/*[, keyring], options*/); } - - /** - * @param {OpenPgpKeyModel} openPgpKeyToRemove - * @returns {void} - */ - deleteOpenPgpKey(openPgpKeyToRemove) { - if (openPgpKeyToRemove && openPgpKeyToRemove.deleteAccess()) { - this.openPgpKeyForDeletion(null); - PgpUserStore.deleteKey(openPgpKeyToRemove); - } - } } diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index c5dccf570..18773cebc 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -15,6 +15,9 @@ import { delegateRunOnDestroy } from 'Common/UtilsUser'; import Remote from 'Remote/User/Fetch'; +import { showScreenPopup } from 'Knoin/Knoin'; +import { ViewOpenPgpKeyPopupView } from 'View/Popup/ViewOpenPgpKey'; + const findKeyByHex = (keys, hash) => keys.find(item => item && (hash === item.id || item.ids.includes(hash))); @@ -35,44 +38,62 @@ const while (i--) { key = await openpgp.readKey({armoredKey:armoredKeys[i]}); if (!key.err) { - const aEmails = []; - if (key.users) { - key.users.forEach(user => { - if (user.userID.email) { - aEmails.push(user.userID.email); - } - }); - } - keys.push({ - id: key.getKeyID().toHex(), - fingerprint: key.getFingerprint(), - can_encrypt: !!key.getEncryptionKey(), - can_sign: !!key.getSigningKey(), - emails: aEmails, - armor: armoredKeys[i], - deleteAccess: ko.observable(false) - }); -// key.getUserIDs() -// key.getPrimaryUser() + keys.push(new OpenPgpKeyModel(armoredKeys[i], key)); } } } return keys; -/* - }, - storeKeys = async (itemname, keys) => { - let armoredKeys = [], i = arrayLength(keys); - if (i) { - while (i--) { - armoredKeys.push(await keys[i].armor()); - } - storage.setItem(itemname, JSON.stringify(armoredKeys)); - } else { - storage.removeItem(itemname); - } -*/ }; +class OpenPgpKeyModel { + constructor(armor, key) { + this.key = key; + const aEmails = []; + if (key.users) { + key.users.forEach(user => { + if (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.deleteAccess = ko.observable(false); + this.openForDeletion = ko.observable(null).deleteAccessHelper(); +// key.getUserIDs() +// key.getPrimaryUser() + } + + view() { + showScreenPopup(ViewOpenPgpKeyPopupView, [this]); + } + + remove() { + if (this.deleteAccess()) { + this.openPgpKeyForDeletion(null); + let armoredKeys = [], itemname = publicKeysItem; + if (this.key.isPrivate()) { + itemname = privateKeysItem; + PgpUserStore.openpgpPrivateKeys.remove(this); + armoredKeys = PgpUserStore.openpgpPrivateKeys.map(item => item.armor); + } else { + PgpUserStore.openpgpPublicKeys.remove(this); + armoredKeys = PgpUserStore.openpgpPublicKeys.map(item => item.armor); + } + delegateRunOnDestroy(this); + if (armoredKeys.length) { + storage.setItem(itemname, JSON.stringify(armoredKeys)); + } else { + storage.removeItem(itemname); + } + } + } +} + export const PgpUserStore = new class { constructor() { /** @@ -289,33 +310,6 @@ export const PgpUserStore = new class { * OpenPGP.js */ - /** - * @param {OpenPgpKeyModel} openPgpKeyToRemove - * @returns {void} - */ - deleteKey(openPgpKeyToRemove) { - const openpgpKeyring = this.openpgpKeyring; - if (openPgpKeyToRemove && openPgpKeyToRemove.deleteAccess() && openpgpKeyring) { - let items = [ - this.openpgpPrivateKeys.find(key => openPgpKeyToRemove === key), - this.openpgpPublicKeys.find(key => openPgpKeyToRemove === key) - ]; - if (items[0]) { - this.openpgpPrivateKeys.remove(items[0]); - openpgpKeyring.privateKeys.removeForId(items[0].guid); - delegateRunOnDestroy(items[0]); - } - if (items[1]) { - this.openpgpPublicKeys.remove(items[1]); - openpgpKeyring.publicKeys.removeForId(items[1].guid); - delegateRunOnDestroy(items[1]); - } - if (items[0] || items[1]) { - openpgpKeyring.store(); - } - } - } - /* decryptMessage(message, recipients, fCallback) { if (message && message.getEncryptionKeyIds) { @@ -385,7 +379,7 @@ export const PgpUserStore = new class { // findPublicKeysBySigningKeyIds const publicKeys = signingKeyIds.map(id => { const key = id && id.toHex ? findKeyByHex(this.openpgpPublicKeys, id.toHex()) : null; - return key ? key.getNativeKeys() : [null]; + return key ? key.key : [null]; }).flat().filter(v => v); if (publicKeys && publicKeys.length) { try { diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index 7e887e8b5..6f6dee69e 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -323,12 +323,12 @@
🔒 - +
✍️ - +
Private keys - + 🔒 - - 🗑 + 🗑 Public keys - + 🔑 - - 🗑 + 🗑