From a99a9e76a28e0cfcc1162d745760b826dd86656a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 6 Oct 2021 02:19:53 +0300 Subject: [PATCH 01/79] wip issue #609 --- Core/source/mobile-interface/validate-input.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index ee0e6e8ad..83b4704b1 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -17,7 +17,7 @@ export namespace NodeRequest { export type composeEmail = composeEmailPlain | composeEmailEncrypted; export type encryptMsg = { pubKeys: string[] }; export type encryptFile = { pubKeys: string[], name: string }; - export type parseDecryptMsg = { keys: PrvKeyInfo[], msgPwd?: string, isEmail?: boolean }; + export type parseDecryptMsg = { keys: PrvKeyInfo[], msgPwd?: string, isEmail?: boolean, verificationPubkeys?: string[] }; export type decryptFile = { keys: PrvKeyInfo[], msgPwd?: string }; export type parseDateStr = { dateStr: string }; export type zxcvbnStrengthBar = { guesses: number, purpose: 'passphrase', value: undefined } | { value: string, purpose: 'passphrase', guesses: undefined }; @@ -60,7 +60,7 @@ export class ValidateInput { } public static parseDecryptMsg = (v: any): NodeRequest.parseDecryptMsg => { - if (isObj(v) && hasProp(v, 'keys', 'PrvKeyInfo[]') && hasProp(v, 'msgPwd', 'string?') && hasProp(v, 'isEmail', 'boolean?')) { + if (isObj(v) && hasProp(v, 'keys', 'PrvKeyInfo[]') && hasProp(v, 'msgPwd', 'string?') && hasProp(v, 'isEmail', 'boolean?') && hasProp(v, 'verificationPubkeys', 'string[]?')) { return v as NodeRequest.parseDecryptMsg; } throw new Error('Wrong request structure for NodeRequest.parseDecryptMsg'); @@ -131,7 +131,7 @@ const isObj = (v: any): v is Obj => { return v && typeof v === 'object'; } -const hasProp = (v: Obj, name: string, type: 'string[]' | 'object' | 'string' | 'number' | 'string?' | 'boolean?' | 'PrvKeyInfo[]' | 'Userid[]' | 'Attachment[]?'): boolean => { +const hasProp = (v: Obj, name: string, type: 'string[]' | 'string[]?' | 'object' | 'string' | 'number' | 'string?' | 'boolean?' | 'PrvKeyInfo[]' | 'Userid[]' | 'Attachment[]?' ): boolean => { if (!isObj(v)) { return false; } @@ -155,6 +155,9 @@ const hasProp = (v: Obj, name: string, type: 'string[]' | 'object' | 'string' | if (type === 'string[]') { return Array.isArray(value) && value.filter((x: any) => typeof x === 'string').length === value.length; } + if (type === 'string[]?') { + return typeof value === 'undefined' || Array.isArray(value) && value.filter((x: any) => typeof x === 'string').length === value.length; + } if (type === 'PrvKeyInfo[]') { return Array.isArray(value) && value.filter((ki: any) => hasProp(ki, 'private', 'string') && hasProp(ki, 'longid', 'string') && hasProp(ki, 'passphrase', 'string?')).length === value.length; } From b41c79f23f19ce6929de2137fe70310ba2a6758b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 6 Oct 2021 02:30:27 +0300 Subject: [PATCH 02/79] wip --- Core/source/core/pgp-msg.ts | 8 ++++---- Core/source/mobile-interface/endpoints.ts | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 40c67b6d7..7387616b5 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -19,7 +19,7 @@ export namespace PgpMsgMethod { export namespace Arg { export type Encrypt = { pubkeys: string[], signingPrv?: OpenPGP.key.Key, pwd?: string, data: Uint8Array, filename?: string, armor: boolean, date?: Date }; export type Type = { data: Uint8Array }; - export type Decrypt = { kisWithPp: PrvKeyInfo[], encryptedData: Uint8Array, msgPwd?: string }; + export type Decrypt = { kisWithPp: PrvKeyInfo[], encryptedData: Uint8Array, msgPwd?: string, verificationPubkeys?: string[] }; export type DiagnosePubkeys = { privateKis: KeyInfo[], message: Uint8Array }; export type VerifyDetached = { plaintext: Uint8Array, sigText: Uint8Array }; } @@ -159,7 +159,7 @@ export class PgpMsg { return await PgpMsg.verify(message, keys.forVerification, keys.verificationContacts[0]); } - public static decrypt: PgpMsgMethod.Decrypt = async ({ kisWithPp, encryptedData, msgPwd }) => { + public static decrypt: PgpMsgMethod.Decrypt = async ({ kisWithPp, encryptedData, msgPwd, verificationPubkeys }) => { let prepared: PreparedForDecrypt; const longids: DecryptError$longids = { message: [], matching: [], chosen: [], needPassphrase: [] }; try { @@ -167,7 +167,7 @@ export class PgpMsg { } catch (formatErr) { return { success: false, error: { type: DecryptErrTypes.format, message: String(formatErr) }, longids }; } - const keys = await PgpMsg.getSortedKeys(kisWithPp, prepared.message); + const keys = await PgpMsg.getSortedKeys(kisWithPp, prepared.message, verificationPubkeys); longids.message = keys.encryptedFor; longids.matching = keys.prvForDecrypt.map(ki => ki.longid); longids.chosen = keys.prvForDecryptDecrypted.map(ki => ki.longid); @@ -311,7 +311,7 @@ export class PgpMsg { } } - private static getSortedKeys = async (kiWithPp: PrvKeyInfo[], msg: OpenpgpMsgOrCleartext): Promise => { + private static getSortedKeys = async (kiWithPp: PrvKeyInfo[], msg: OpenpgpMsgOrCleartext, verificationPubkeys?: string[]): Promise => { const keys: SortedKeysForDecrypt = { verificationContacts: [], forVerification: [], diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index d10f51587..b547f7d66 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -78,7 +78,7 @@ export class Endpoints { } public parseDecryptMsg = async (uncheckedReq: any, data: Buffers): Promise => { - const { keys: kisWithPp, msgPwd, isEmail } = ValidateInput.parseDecryptMsg(uncheckedReq); + const { keys: kisWithPp, msgPwd, isEmail, verificationPubkeys } = ValidateInput.parseDecryptMsg(uncheckedReq); const rawBlocks: MsgBlock[] = []; // contains parsed, unprocessed / possibly encrypted data let rawSigned: string | undefined = undefined; let subject: string | undefined = undefined; @@ -100,7 +100,7 @@ export class Endpoints { sequentialProcessedBlocks.push({ type: 'verifiedMsg', content: Str.asEscapedHtml(rawBlock.content.toString()), verifyRes: verify, complete: true }); } } else if (rawBlock.type === 'encryptedMsg' || rawBlock.type === 'signedMsg') { - const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.content) }); + const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.content), verificationPubkeys }); if (decryptRes.success) { if (decryptRes.isEncrypted) { const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content); @@ -124,7 +124,7 @@ export class Endpoints { } } else if (rawBlock.type === 'encryptedAtt' && rawBlock.attMeta && /^(0x)?[A-Fa-f0-9]{16,40}\.asc\.pgp$/.test(rawBlock.attMeta.name || '')) { // encrypted pubkey attached - const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.attMeta.data || '') }); + const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.attMeta.data || ''), verificationPubkeys }); if (decryptRes.content) { sequentialProcessedBlocks.push({ type: 'publicKey', content: decryptRes.content.toString(), complete: true }); } else { @@ -185,9 +185,9 @@ export class Endpoints { return fmtRes({ text, replyType, subject }, Buf.fromUtfStr(blocks.map(b => JSON.stringify(b)).join('\n'))); } - public decryptFile = async (uncheckedReq: any, data: Buffers): Promise => { + public decryptFile = async (uncheckedReq: any, data: Buffers, verificationPubkeys?: string[]): Promise => { const { keys: kisWithPp, msgPwd } = ValidateInput.decryptFile(uncheckedReq); - const decryptedMeta = await PgpMsg.decrypt({ kisWithPp, encryptedData: Buf.concat(data), msgPwd }); + const decryptedMeta = await PgpMsg.decrypt({ kisWithPp, encryptedData: Buf.concat(data), msgPwd, verificationPubkeys }); if (!decryptedMeta.success) { decryptedMeta.message = undefined; return fmtRes(decryptedMeta); From ea83b54b6b67b63ab8f330903bf7b680c88085e5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 6 Oct 2021 02:36:25 +0300 Subject: [PATCH 03/79] wip --- Core/source/core/pgp-msg.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 7387616b5..c44ed597e 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -155,6 +155,7 @@ export class PgpMsg { public static verifyDetached: PgpMsgMethod.VerifyDetached = async ({ plaintext, sigText }) => { const message = openpgp.message.fromText(Buf.fromUint8(plaintext).toUtfStr()); await message.appendSignature(Buf.fromUint8(sigText).toUtfStr()); + // Q: Should we add verificationPubkeys here????? const keys = await PgpMsg.getSortedKeys([], message); return await PgpMsg.verify(message, keys.forVerification, keys.verificationContacts[0]); } @@ -322,9 +323,19 @@ export class PgpMsg { prvForDecryptDecrypted: [], prvForDecryptWithoutPassphrases: [], }; - const encryptedForKeyids = msg instanceof openpgp.message.Message ? (msg as OpenPGP.message.Message).getEncryptionKeyIds() : []; + const encryptedForKeyids = msg instanceof openpgp.message.Message + ? (msg as OpenPGP.message.Message).getEncryptionKeyIds() + : []; keys.encryptedFor = await PgpKey.longids(encryptedForKeyids); - await PgpMsg.cryptoMsgGetSignedBy(msg, keys); + if(typeof verificationPubkeys !== 'undefined') { + keys.forVerification = []; + for (const verificationPubkey of verificationPubkeys) { + const { keys: keysForVerification } = await openpgp.key.readArmored(verificationPubkey); + keys.forVerification.push(...keysForVerification); + } + } else { + await PgpMsg.cryptoMsgGetSignedBy(msg, keys); + } if (keys.encryptedFor.length) { for (const ki of kiWithPp) { ki.parsed = await PgpKey.read(ki.private); // todo From ca80ec84f47faadaa4b05fb349b3152f6d89214b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 00:37:37 +0300 Subject: [PATCH 04/79] Remove stuff related to keys.verificationContacts --- Core/source/core/pgp-msg.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index c44ed597e..248e0d8f3 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -31,7 +31,6 @@ export namespace PgpMsgMethod { } type SortedKeysForDecrypt = { - verificationContacts: Contact[]; forVerification: OpenPGP.key.Key[]; encryptedFor: string[]; signedBy: string[]; @@ -53,7 +52,7 @@ type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: Open type OpenpgpMsgOrCleartext = OpenPGP.message.Message | OpenPGP.cleartext.CleartextMessage; -export type VerifyRes = { signer?: string; contact?: Contact; match: boolean | null; error?: string; }; +export type VerifyRes = { signer?: string; match: boolean | null; error?: string; }; export type PgpMsgTypeResult = { armored: boolean, type: MsgBlockType } | undefined; export type DecryptResult = DecryptSuccess | DecryptError; export type DiagnoseMsgPubkeysResult = { found_match: boolean, receivers: number, }; @@ -123,8 +122,8 @@ export class PgpMsg { return await openpgp.stream.readToEnd((signRes as OpenPGP.SignArmorResult).data); } - public static verify = async (msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.message.Verification[], pubs: OpenPGP.key.Key[], contact?: Contact): Promise => { - const sig: VerifyRes = { contact, match: null }; // tslint:disable-line:no-null-keyword + public static verify = async (msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.message.Verification[], pubs: OpenPGP.key.Key[]): Promise => { + const sig: VerifyRes = { match: null }; // tslint:disable-line:no-null-keyword try { // While this looks like bad method API design, it's here to ensure execution order when 1) reading data, 2) verifying, 3) processing signatures // Else it will hang trying to read a stream: https://github.com/openpgpjs/openpgpjs/issues/916#issuecomment-510620625 @@ -157,7 +156,7 @@ export class PgpMsg { await message.appendSignature(Buf.fromUint8(sigText).toUtfStr()); // Q: Should we add verificationPubkeys here????? const keys = await PgpMsg.getSortedKeys([], message); - return await PgpMsg.verify(message, keys.forVerification, keys.verificationContacts[0]); + return await PgpMsg.verify(message, keys.forVerification); } public static decrypt: PgpMsgMethod.Decrypt = async ({ kisWithPp, encryptedData, msgPwd, verificationPubkeys }) => { @@ -175,7 +174,7 @@ export class PgpMsg { longids.needPassphrase = keys.prvForDecryptWithoutPassphrases.map(ki => ki.longid); const isEncrypted = !prepared.isCleartext; if (!isEncrypted) { - const signature = await PgpMsg.verify(prepared.message, keys.forVerification, keys.verificationContacts[0]); + const signature = await PgpMsg.verify(prepared.message, keys.forVerification); const text = await openpgp.stream.readToEnd(prepared.message.getText()!); return { success: true, content: Buf.fromUtfStr(text), isEncrypted, signature }; } @@ -198,7 +197,7 @@ export class PgpMsg { await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); // we can only figure out who signed the msg once it's decrypted const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang const content = new Buf(await openpgp.stream.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang - const signature = verifyResults ? await PgpMsg.verify(verifyResults, [], keys.verificationContacts[0]) : undefined; // evaluate verify results third to prevent stream hang + const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang if (!prepared.isCleartext && (prepared.message as OpenPGP.message.Message).packets.filterByTag(openpgp.enums.packet.symmetricallyEncrypted).length) { const noMdc = 'Security threat!\n\nMessage is missing integrity checks (MDC). The sender should update their outdated software.\n\nDisplay the message at your own risk.'; return { success: false, content, error: { type: DecryptErrTypes.noMdc, message: noMdc }, message: prepared.message, longids, isEncrypted }; @@ -302,10 +301,10 @@ export class PgpMsg { private static cryptoMsgGetSignedBy = async (msg: OpenpgpMsgOrCleartext, keys: SortedKeysForDecrypt) => { keys.signedBy = Value.arr.unique(await PgpKey.longids(msg.getSigningKeyIds ? msg.getSigningKeyIds() : [])); if (keys.signedBy.length && typeof Store.dbContactGet === 'function') { - const verificationContacts = await Store.dbContactGet(undefined, keys.signedBy); - keys.verificationContacts = verificationContacts.filter(contact => contact && contact.pubkey) as Contact[]; + const signerContacts = (await Store.dbContactGet(undefined, keys.signedBy)) + .filter(contact => contact && contact.pubkey) as Contact[]; keys.forVerification = []; - for (const contact of keys.verificationContacts) { + for (const contact of signerContacts) { const { keys: keysForVerification } = await openpgp.key.readArmored(contact.pubkey!); keys.forVerification.push(...keysForVerification); } @@ -314,7 +313,6 @@ export class PgpMsg { private static getSortedKeys = async (kiWithPp: PrvKeyInfo[], msg: OpenpgpMsgOrCleartext, verificationPubkeys?: string[]): Promise => { const keys: SortedKeysForDecrypt = { - verificationContacts: [], forVerification: [], encryptedFor: [], signedBy: [], From 12e4bebfe18465943fcf7c68bd09e687f6105b5f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 00:41:59 +0300 Subject: [PATCH 05/79] wip --- Core/source/core/pgp-msg.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 248e0d8f3..e235dbafb 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -325,7 +325,7 @@ export class PgpMsg { ? (msg as OpenPGP.message.Message).getEncryptionKeyIds() : []; keys.encryptedFor = await PgpKey.longids(encryptedForKeyids); - if(typeof verificationPubkeys !== 'undefined') { + if (typeof verificationPubkeys !== 'undefined') { keys.forVerification = []; for (const verificationPubkey of verificationPubkeys) { const { keys: keysForVerification } = await openpgp.key.readArmored(verificationPubkey); From 852b76ac69d558ff437b1a2e19e8816c5fe17ff2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 00:48:32 +0300 Subject: [PATCH 06/79] add test stubs --- Core/source/test.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Core/source/test.ts b/Core/source/test.ts index ff979c8b5..bed1d0b2f 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -558,3 +558,33 @@ ava.default('can process dirty html without throwing', async t => { expect(clean).to.not.contain('src="http'); t.pass(); }); + +ava.default('verify encrypted+signed message by providing it correct public key', async t => { + // TODO: implement the test + t.pass(); +}); + +ava.default('verify encrypted+signed message by providing it one wrong and one correct', async t => { + // TODO: implement the test + t.pass(); +}); + +ava.default('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { + // TODO: implement the test + t.pass(); +}); + +ava.default('verify plain-text signed message by providing it correct key', async t => { + // TODO: implement the test + t.pass(); +}); + +ava.default('verify plain-text signed message by providing it wrong key (fail: cannot verify)', async t => { + // TODO: implement the test + t.pass(); +}); + +ava.default('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { + // TODO: implement the test + t.pass(); +}); From c72883bed5657e77b223fe94d225fefcc5bb1c2c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 19:21:16 +0300 Subject: [PATCH 07/79] wip --- Core/source/core/pgp-msg.ts | 2 +- Core/source/test.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index e235dbafb..3ce95bc5a 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -194,7 +194,7 @@ export class PgpMsg { const passwords = msgPwd ? [msgPwd] : undefined; const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!); const decrypted = await (prepared.message as OpenPGP.message.Message).decrypt(privateKeys, passwords, undefined, false); - await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); // we can only figure out who signed the msg once it's decrypted + await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys, verificationPubkeys); // we can only figure out who signed the msg once it's decrypted const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang const content = new Buf(await openpgp.stream.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang diff --git a/Core/source/test.ts b/Core/source/test.ts index bed1d0b2f..8be27bbd6 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -588,3 +588,8 @@ ava.default('verify plain-text signed message that you edited after signing. Thi // TODO: implement the test t.pass(); }); + +ava.default('verify signed message with detached signature by providing it correct key', async t => { + // TODO: implement the test + t.pass(); +}); From 6818f90f8eb35f703a9618848db98c065c3590d1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 21:45:17 +0300 Subject: [PATCH 08/79] wip --- Core/source/core/pgp-msg.ts | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 3ce95bc5a..5c587d6c6 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -194,7 +194,9 @@ export class PgpMsg { const passwords = msgPwd ? [msgPwd] : undefined; const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!); const decrypted = await (prepared.message as OpenPGP.message.Message).decrypt(privateKeys, passwords, undefined, false); - await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys, verificationPubkeys); // we can only figure out who signed the msg once it's decrypted + // we can only figure out who signed the msg once it's decrypted + await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); + await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang const content = new Buf(await openpgp.stream.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang @@ -299,13 +301,16 @@ export class PgpMsg { } private static cryptoMsgGetSignedBy = async (msg: OpenpgpMsgOrCleartext, keys: SortedKeysForDecrypt) => { - keys.signedBy = Value.arr.unique(await PgpKey.longids(msg.getSigningKeyIds ? msg.getSigningKeyIds() : [])); - if (keys.signedBy.length && typeof Store.dbContactGet === 'function') { - const signerContacts = (await Store.dbContactGet(undefined, keys.signedBy)) - .filter(contact => contact && contact.pubkey) as Contact[]; + keys.signedBy = Value.arr.unique(await PgpKey.longids( + msg.getSigningKeyIds ? msg.getSigningKeyIds() : [])); + } + + private static populateKeysForVerification = async (keys: SortedKeysForDecrypt, + verificationPubkeys?: string[]) => { + if (typeof verificationPubkeys !== 'undefined') { keys.forVerification = []; - for (const contact of signerContacts) { - const { keys: keysForVerification } = await openpgp.key.readArmored(contact.pubkey!); + for (const verificationPubkey of verificationPubkeys) { + const { keys: keysForVerification } = await openpgp.key.readArmored(verificationPubkey); keys.forVerification.push(...keysForVerification); } } @@ -325,15 +330,8 @@ export class PgpMsg { ? (msg as OpenPGP.message.Message).getEncryptionKeyIds() : []; keys.encryptedFor = await PgpKey.longids(encryptedForKeyids); - if (typeof verificationPubkeys !== 'undefined') { - keys.forVerification = []; - for (const verificationPubkey of verificationPubkeys) { - const { keys: keysForVerification } = await openpgp.key.readArmored(verificationPubkey); - keys.forVerification.push(...keysForVerification); - } - } else { - await PgpMsg.cryptoMsgGetSignedBy(msg, keys); - } + await PgpMsg.cryptoMsgGetSignedBy(msg, keys); + await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); if (keys.encryptedFor.length) { for (const ki of kiWithPp) { ki.parsed = await PgpKey.read(ki.private); // todo From 947f15c3c55147055811d9f48e6e8f2437fa7563 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 21:49:53 +0300 Subject: [PATCH 09/79] wip --- Core/source/core/pgp-msg.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 5c587d6c6..9af9e5c00 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -336,9 +336,11 @@ export class PgpMsg { for (const ki of kiWithPp) { ki.parsed = await PgpKey.read(ki.private); // todo // this is inefficient because we are doing unnecessary parsing of all keys here - // better would be to compare to already stored KeyInfo, however KeyInfo currently only holds primary longid, not longids of subkeys - // while messages are typically encrypted for subkeys, thus we have to parse the key to get the info - // we are filtering here to avoid a significant performance issue of having to attempt decrypting with all keys simultaneously + // better would be to compare to already stored KeyInfo, however KeyInfo currently + // only holds primary longid, not longids of subkeys, while messages are typically + // encrypted for subkeys, thus we have to parse the key to get the info + // we are filtering here to avoid a significant performance issue of having + // to attempt decrypting with all keys simultaneously for (const longid of await Promise.all(ki.parsed.getKeyIds().map(({ bytes }) => PgpKey.longid(bytes)))) { if (keys.encryptedFor.includes(longid!)) { keys.prvMatching.push(ki); From 3085fed48cdfa0035c7aa6f1cc11d5a6918ddff3 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 21:51:37 +0300 Subject: [PATCH 10/79] wip --- Core/source/core/pgp-msg.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 9af9e5c00..98ea98692 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -196,7 +196,7 @@ export class PgpMsg { const decrypted = await (prepared.message as OpenPGP.message.Message).decrypt(privateKeys, passwords, undefined, false); // we can only figure out who signed the msg once it's decrypted await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); - await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); + await PgpMsg.populateKeysForVerification(verificationPubkeys, keys); const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang const content = new Buf(await openpgp.stream.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang @@ -305,8 +305,7 @@ export class PgpMsg { msg.getSigningKeyIds ? msg.getSigningKeyIds() : [])); } - private static populateKeysForVerification = async (keys: SortedKeysForDecrypt, - verificationPubkeys?: string[]) => { + private static populateKeysForVerification = async (verificationPubkeys?: string[], keys: SortedKeysForDecrypt) => { if (typeof verificationPubkeys !== 'undefined') { keys.forVerification = []; for (const verificationPubkey of verificationPubkeys) { @@ -331,7 +330,7 @@ export class PgpMsg { : []; keys.encryptedFor = await PgpKey.longids(encryptedForKeyids); await PgpMsg.cryptoMsgGetSignedBy(msg, keys); - await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); + await PgpMsg.populateKeysForVerification(verificationPubkeys, keys); if (keys.encryptedFor.length) { for (const ki of kiWithPp) { ki.parsed = await PgpKey.read(ki.private); // todo From a2b3ea6e755c3f5bdf48f5eb0453707d45b828f1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 21:52:57 +0300 Subject: [PATCH 11/79] wip --- Core/source/core/pgp-msg.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 98ea98692..9af9e5c00 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -196,7 +196,7 @@ export class PgpMsg { const decrypted = await (prepared.message as OpenPGP.message.Message).decrypt(privateKeys, passwords, undefined, false); // we can only figure out who signed the msg once it's decrypted await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); - await PgpMsg.populateKeysForVerification(verificationPubkeys, keys); + await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang const content = new Buf(await openpgp.stream.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang @@ -305,7 +305,8 @@ export class PgpMsg { msg.getSigningKeyIds ? msg.getSigningKeyIds() : [])); } - private static populateKeysForVerification = async (verificationPubkeys?: string[], keys: SortedKeysForDecrypt) => { + private static populateKeysForVerification = async (keys: SortedKeysForDecrypt, + verificationPubkeys?: string[]) => { if (typeof verificationPubkeys !== 'undefined') { keys.forVerification = []; for (const verificationPubkey of verificationPubkeys) { @@ -330,7 +331,7 @@ export class PgpMsg { : []; keys.encryptedFor = await PgpKey.longids(encryptedForKeyids); await PgpMsg.cryptoMsgGetSignedBy(msg, keys); - await PgpMsg.populateKeysForVerification(verificationPubkeys, keys); + await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); if (keys.encryptedFor.length) { for (const ki of kiWithPp) { ki.parsed = await PgpKey.read(ki.private); // todo From a89d924b54646f132a011a3304ef4166e416d327 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 21:53:58 +0300 Subject: [PATCH 12/79] wip --- Core/source/core/pgp-msg.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 9af9e5c00..0d512b4dc 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -2,7 +2,7 @@ 'use strict'; -import { Contact, KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key.js'; +import { KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key.js'; import { MsgBlock, MsgBlockType } from './msg-block.js'; import { Str, Value } from './common.js'; From eefddc61cd97f9199a1429e5a2a9fe48602efa2c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 21:55:14 +0300 Subject: [PATCH 13/79] wip --- Core/source/platform/store.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index 97c8cd2d8..552af2a23 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -12,10 +12,6 @@ const keyLongid = (k: OpenPGP.key.Key) => openpgp.util.str_to_hex(k.getKeyId().b export class Store { - static dbContactGet = async (db: void, emailOrLongid: string[]): Promise<(Contact | undefined)[]> => { - return []; - } - static decryptedKeyCacheSet = (k: OpenPGP.key.Key) => { Store.keyCacheRenewExpiry(); KEY_CACHE[keyLongid(k)] = k; From da7915f86d73fcc44a6dfb178570edd4d9904807 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 7 Oct 2021 22:55:44 +0300 Subject: [PATCH 14/79] wip --- Core/source/platform/store.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index 552af2a23..cdf7a48a4 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,7 +2,6 @@ 'use strict'; -import { Contact } from '../core/pgp-key.js'; import { openpgp } from '../core/pgp.js'; let KEY_CACHE: { [longidOrArmoredKey: string]: OpenPGP.key.Key } = {}; From 69e314ad7d651883ac6039e6d026f9e41cf0b1d0 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 10 Oct 2021 23:21:23 +0300 Subject: [PATCH 15/79] wip --- Core/source/gen-compat-assets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 354472c88..2e6a94a47 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -6,7 +6,7 @@ // @ts-ignore - it cannot figure out the types, because we don't want to install them from npm // nodejs-mobile expects it as global, but this test runs as standard Nodejs -global.openpgp = require('openpgp'); // remove it and you'll see what I mean +//global.openpgp = require('openpgp'); // remove it and you'll see what I mean import * as ava from 'ava'; From 7ef6f309b2de6ce87b2d69686869bc63c760d826 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 10 Oct 2021 23:45:22 +0300 Subject: [PATCH 16/79] wip --- Core/source/gen-compat-assets.ts | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 2e6a94a47..4d6732cca 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -10,7 +10,7 @@ import * as ava from 'ava'; -import { AvaContext, writeFile } from './test/test-utils'; +import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; @@ -86,6 +86,22 @@ Content-Type: text/plain; charset="UTF-8" ${text.toString()} `.replace(/^\n/, '')); +// TODO: maybe modify "Openpgp" +const mimeEmail2 = (t: AvaContext, text: Buffer | string) => Buffer.from(` +Delivered-To: flowcrypt.compatibility@gmail.com +Return-Path: +Openpgp: id=6D24791A5B106262B06217C606CA553EC2455D70 +From: cryptup.tester@gmail.com +MIME-Version: 1.0 +Date: Thu, 2 Nov 2017 17:54:14 -0700 +Message-ID: +Subject: ${subject(t)} +To: flowcrypt.compatibility@gmail.com +Content-Type: text/plain; charset="UTF-8" + +${text.toString()} +`.replace(/^\n/, '')); + const mimePgp = (t: AvaContext, text: string | Buffer) => Buffer.from(` Content-Type: multipart/mixed; boundary="PpujspXwR9sayhr0t4sBaTxoXX6dlYhLU"; protected-headers="v1" @@ -181,3 +197,15 @@ ava.default('mime-email-plain-html.txt', async t => { await write(t, plainHtmlMimeEmail(t)); t.pass(); }); + +ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { + const { keys } = getKeypairs('rsa1'); + const { data } = await PgpMsg.encrypt({ data: text, signingPrv: keys[0].private, pwd: keys[0].passphrase, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + await write(t, mimeEmail2(t, data)); + t.pass(); +}); + +ava.default('mime-email-plain-signed.txt', async t => { + await write(t, mimeEmail2(t, text)); + t.pass(); +}); From 0a8b54172083f4fad8a2d3215b5062cda1510e65 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 10 Oct 2021 23:49:25 +0300 Subject: [PATCH 17/79] wip --- Core/source/gen-compat-assets.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 4d6732cca..43fc5aabe 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -13,6 +13,7 @@ import * as ava from 'ava'; import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; +import { openpgp } from './core/pgp'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); @@ -200,7 +201,8 @@ ava.default('mime-email-plain-html.txt', async t => { ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); - const { data } = await PgpMsg.encrypt({ data: text, signingPrv: keys[0].private, pwd: keys[0].passphrase, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pwd: keys[0].passphrase, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; await write(t, mimeEmail2(t, data)); t.pass(); }); From fc0ee3aa7256e142d5a7eb5073421d1089d1914c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 10 Oct 2021 23:53:39 +0300 Subject: [PATCH 18/79] wip --- Core/source/gen-compat-assets.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 43fc5aabe..7657105fc 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -202,7 +202,8 @@ ava.default('mime-email-plain-html.txt', async t => { ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; - const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pwd: keys[0].passphrase, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); + const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; await write(t, mimeEmail2(t, data)); t.pass(); }); From f95eca47d001e9a427d4730701bf6fa3282a3ccb Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 10 Oct 2021 23:54:54 +0300 Subject: [PATCH 19/79] Add encrypted+signed email --- ...ime-email-encrypted-inline-text-signed.txt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt diff --git a/Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt b/Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt new file mode 100644 index 000000000..1212c9177 --- /dev/null +++ b/Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt @@ -0,0 +1,33 @@ +Delivered-To: flowcrypt.compatibility@gmail.com +Return-Path: +Openpgp: id=6D24791A5B106262B06217C606CA553EC2455D70 +From: cryptup.tester@gmail.com +MIME-Version: 1.0 +Date: Thu, 2 Nov 2017 17:54:14 -0700 +Message-ID: +Subject: mime email encrypted inline text signed +To: flowcrypt.compatibility@gmail.com +Content-Type: text/plain; charset="UTF-8" + +-----BEGIN PGP MESSAGE----- +Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption +Comment: Seamlessly send and receive encrypted email + +wcBMAwurnAGLJl0iAQf/Xu7ma7uF0HULsJctrcmSyzmsZ9HrBG6ITVs/Betd +0o6KVBnBYPrZYHN0Kkj/WlszRBUOapvA8gotXtXjTBYbRFGzL5PFuPGCxGzd +a1YYGAOyfk9VE8p0dZa6mCYEGJYGaCNoqh0xJKzdG2HNzCrY+samnA27nPXb +KZm51zMdKtL4iWc+RZ4P/lz4H0T58QHECNFK4S/aK4vtS8u9sAQma6jGoThY +PQqE4m3VYC8jRzQbdT+V584qKoAz8ELD/CMr1fwJep8RX23AR6psQno7XAnV +0sEGl8PLz9KiXp46UHcu3LNNcQihlADxB6iYvDqnF7KocTDUVQ19YhHJaOK5 +6NLAsgHYv0PGeUBLUcl5YRQqoQYW/Ryf/nOv0btEKQanjvsGQDnS/JtTr67J +L8egC4gtyA8Bz7+oS9a+p6d2Zk3ZhuPcqzEVzopBgnQaLfN2DlRZnhdqWoIB +0ofDHkn+R6Lx9oxANzRIFuT4xuxPnRknDhln+C3gTGpCSrM8amrqdng3IhGt +F7k0Xsax7AWZtkvKNaaeAQSf9A42YoiacTTZXHqVJUJbyMk2ryM9zEng0xyk +lLXIgBwVTXouM+D8kXWVDlpzwVksVw2jU/ITkyngou3X/ZKhBGPHd8VnMyni +r/slRzrvvzN525mljf0h0Ku49V+7xyFw45JmbrrW5soLS07PmpsmVBka4I8j +SReMsZrEPyZYpZStDpz0PPQv6qMijL4/gBB+wwjCl8eNmNV8ZZGvGcwgs972 +l45ijcVFaNdAmh5CXfCOnP8+GlNbIpkBywvPUZ4ZJB2BVY4U0wDjqJxbBIBP +NUZLDZ7yTlLeddP9kWA= +=NGUK +-----END PGP MESSAGE----- + From 72d51096b944a44f781a8f231a7b43575daafd88 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:01:55 +0300 Subject: [PATCH 20/79] wip --- Core/source/gen-compat-assets.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 7657105fc..8e0f73a59 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -87,12 +87,12 @@ Content-Type: text/plain; charset="UTF-8" ${text.toString()} `.replace(/^\n/, '')); -// TODO: maybe modify "Openpgp" +// Used to generate encrypted+signed and plaintext signed emails const mimeEmail2 = (t: AvaContext, text: Buffer | string) => Buffer.from(` Delivered-To: flowcrypt.compatibility@gmail.com Return-Path: -Openpgp: id=6D24791A5B106262B06217C606CA553EC2455D70 -From: cryptup.tester@gmail.com +Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 +From: flowcrypt.compatibility@gmail.com MIME-Version: 1.0 Date: Thu, 2 Nov 2017 17:54:14 -0700 Message-ID: @@ -202,6 +202,7 @@ ava.default('mime-email-plain-html.txt', async t => { ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; await write(t, mimeEmail2(t, data)); From 644c9b2f32685b7b880af0d9178c48de6ca03763 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:03:55 +0300 Subject: [PATCH 21/79] wip --- Core/source/gen-compat-assets.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 8e0f73a59..f577c46bd 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -88,7 +88,7 @@ ${text.toString()} `.replace(/^\n/, '')); // Used to generate encrypted+signed and plaintext signed emails -const mimeEmail2 = (t: AvaContext, text: Buffer | string) => Buffer.from(` +const signedMimeEmail = (t: AvaContext, text: Buffer | string) => Buffer.from(` Delivered-To: flowcrypt.compatibility@gmail.com Return-Path: Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 @@ -205,11 +205,11 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; - await write(t, mimeEmail2(t, data)); + await write(t, signedMimeEmail(t, data)); t.pass(); }); ava.default('mime-email-plain-signed.txt', async t => { - await write(t, mimeEmail2(t, text)); + await write(t, signedMimeEmail(t, text)); t.pass(); }); From 0382533abab6beb53352923e659de624cbb2baa5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:10:48 +0300 Subject: [PATCH 22/79] wip --- Core/source/gen-compat-assets.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index f577c46bd..cf3365a3e 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -202,7 +202,7 @@ ava.default('mime-email-plain-html.txt', async t => { ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; - console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); + // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; await write(t, signedMimeEmail(t, data)); @@ -210,6 +210,11 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { }); ava.default('mime-email-plain-signed.txt', async t => { - await write(t, signedMimeEmail(t, text)); + const { keys } = getKeypairs('rsa1'); + const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + const detached = false; + const data = text.toString(); + const signed = await PgpMsg.sign({ data: data, signingPrv: signingPrv, detached: detached }); + await write(t, signedMimeEmail(t, signed)); t.pass(); }); From 0008014b6cc082f1f420b4ecf50a7a61784ba333 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:12:50 +0300 Subject: [PATCH 23/79] wip --- Core/source/gen-compat-assets.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index cf3365a3e..0bc7a5a87 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -212,9 +212,19 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { ava.default('mime-email-plain-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + const data = text.toString(); const detached = false; + const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: detached }); + await write(t, signedMimeEmail(t, signed)); + t.pass(); +}); + +ava.default('mime-email-plain-signed-detached.txt', async t => { + const { keys } = getKeypairs('rsa1'); + const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; const data = text.toString(); - const signed = await PgpMsg.sign({ data: data, signingPrv: signingPrv, detached: detached }); + const detached = true; + const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: detached }); await write(t, signedMimeEmail(t, signed)); t.pass(); }); From 534d7dc7b95ec4aa53964a2e372153324771afba Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:13:04 +0300 Subject: [PATCH 24/79] wip --- Core/source/gen-compat-assets.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 0bc7a5a87..3e5f11946 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -88,7 +88,7 @@ ${text.toString()} `.replace(/^\n/, '')); // Used to generate encrypted+signed and plaintext signed emails -const signedMimeEmail = (t: AvaContext, text: Buffer | string) => Buffer.from(` +const mimeEmail2 = (t: AvaContext, text: Buffer | string) => Buffer.from(` Delivered-To: flowcrypt.compatibility@gmail.com Return-Path: Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 @@ -205,7 +205,7 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; - await write(t, signedMimeEmail(t, data)); + await write(t, mimeEmail2(t, data)); t.pass(); }); @@ -215,7 +215,7 @@ ava.default('mime-email-plain-signed.txt', async t => { const data = text.toString(); const detached = false; const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: detached }); - await write(t, signedMimeEmail(t, signed)); + await write(t, mimeEmail2(t, signed)); t.pass(); }); @@ -225,6 +225,6 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const data = text.toString(); const detached = true; const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: detached }); - await write(t, signedMimeEmail(t, signed)); + await write(t, mimeEmail2(t, signed)); t.pass(); }); From f623892392da2d0139a4d2ad60bc9f0581deb72e Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:15:08 +0300 Subject: [PATCH 25/79] wip --- Core/source/gen-compat-assets.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 3e5f11946..d2170ede3 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -213,8 +213,7 @@ ava.default('mime-email-plain-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; const data = text.toString(); - const detached = false; - const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: detached }); + const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data }); await write(t, mimeEmail2(t, signed)); t.pass(); }); @@ -224,7 +223,7 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; const data = text.toString(); const detached = true; - const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: detached }); + const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: true }); await write(t, mimeEmail2(t, signed)); t.pass(); }); From eb81bb8491dcfb16754a2ea84dadfeebbd3f897a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:15:35 +0300 Subject: [PATCH 26/79] wip --- Core/source/gen-compat-assets.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index d2170ede3..cf1d475a3 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -222,7 +222,6 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; const data = text.toString(); - const detached = true; const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: true }); await write(t, mimeEmail2(t, signed)); t.pass(); From 9d3925c48124325db0342e2e4442c35a8aa9ced2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:25:37 +0300 Subject: [PATCH 27/79] wip --- Core/source/gen-compat-assets.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index cf1d475a3..9397c0510 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -212,6 +212,7 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { ava.default('mime-email-plain-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const data = text.toString(); const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data }); await write(t, mimeEmail2(t, signed)); @@ -221,6 +222,7 @@ ava.default('mime-email-plain-signed.txt', async t => { ava.default('mime-email-plain-signed-detached.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const data = text.toString(); const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: true }); await write(t, mimeEmail2(t, signed)); From 1f9ef13277ddb3585ea9f10221bdb81919cfc54d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:34:13 +0300 Subject: [PATCH 28/79] wip --- Core/source/gen-compat-assets.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 9397c0510..4bfba304f 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -214,7 +214,7 @@ ava.default('mime-email-plain-signed.txt', async t => { const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const data = text.toString(); - const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data }); + const signed = await PgpMsg.sign(signingPrv, data); await write(t, mimeEmail2(t, signed)); t.pass(); }); @@ -224,7 +224,7 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const data = text.toString(); - const signed = await PgpMsg.sign({ signingPrv: signingPrv, data: data, detached: true }); + const signed = await PgpMsg.sign(signingPrv, data, true); await write(t, mimeEmail2(t, signed)); t.pass(); }); From b9fa7bc8e7a33c5270729c2a65a1b9efc237c54f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:37:34 +0300 Subject: [PATCH 29/79] Added signed plaintext emails --- .../mime-email-plain-signed-detached.txt | 25 +++++++++++++++ .../assets/compat/mime-email-plain-signed.txt | 32 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 Core/source/assets/compat/mime-email-plain-signed-detached.txt create mode 100644 Core/source/assets/compat/mime-email-plain-signed.txt diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached.txt b/Core/source/assets/compat/mime-email-plain-signed-detached.txt new file mode 100644 index 000000000..4e9411dc1 --- /dev/null +++ b/Core/source/assets/compat/mime-email-plain-signed-detached.txt @@ -0,0 +1,25 @@ +Delivered-To: flowcrypt.compatibility@gmail.com +Return-Path: +Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 +From: flowcrypt.compatibility@gmail.com +MIME-Version: 1.0 +Date: Thu, 2 Nov 2017 17:54:14 -0700 +Message-ID: +Subject: mime email plain signed detached +To: flowcrypt.compatibility@gmail.com +Content-Type: text/plain; charset="UTF-8" + +-----BEGIN PGP SIGNATURE----- +Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption +Comment: Seamlessly send and receive encrypted email + +wsBcBAEBCAAGBQJhY1x0AAoJEDow9MwKmo8QMR0H/iHkHFr1doJhqIVsSXyQ +bBwYpoaIRHEZlF3RQa3sbkLqXSTzHf81ySb7/oXgd+z5RYYw2vD9bebaInb3 +Ca9FuBrM4ZlnmVVnNpv/nntZZdln+AVq+rEOaLDcHC4nFTC3Z7QwulZn31Hm +b0JcsGAuIDfUZ1mFfFpyCq7KB+XGbV3bc+bUBO0pjKfbsEISBqJxuCzJIr+0 +pIwMSdluQXxtyyqT3aXnoH9jl75dBDDvMEPR3c/I2+k9SWWoYslwhn2TqB94 +RFgwWpw/SH8+1b3lI1AWnkVpkkm8JOnteViHCz85ALd9xkACjq8UavPGLy0v +J6XRgsV1E2RTmydFB6vv/9w= +=quFc +-----END PGP SIGNATURE----- + diff --git a/Core/source/assets/compat/mime-email-plain-signed.txt b/Core/source/assets/compat/mime-email-plain-signed.txt new file mode 100644 index 000000000..0adfa0371 --- /dev/null +++ b/Core/source/assets/compat/mime-email-plain-signed.txt @@ -0,0 +1,32 @@ +Delivered-To: flowcrypt.compatibility@gmail.com +Return-Path: +Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 +From: flowcrypt.compatibility@gmail.com +MIME-Version: 1.0 +Date: Thu, 2 Nov 2017 17:54:14 -0700 +Message-ID: +Subject: mime email plain signed +To: flowcrypt.compatibility@gmail.com +Content-Type: text/plain; charset="UTF-8" + + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +some +汉 +txt +-----BEGIN PGP SIGNATURE----- +Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption +Comment: Seamlessly send and receive encrypted email + +wsBcBAEBCAAGBQJhY1x0AAoJEDow9MwKmo8QMR0H/iHkHFr1doJhqIVsSXyQ +bBwYpoaIRHEZlF3RQa3sbkLqXSTzHf81ySb7/oXgd+z5RYYw2vD9bebaInb3 +Ca9FuBrM4ZlnmVVnNpv/nntZZdln+AVq+rEOaLDcHC4nFTC3Z7QwulZn31Hm +b0JcsGAuIDfUZ1mFfFpyCq7KB+XGbV3bc+bUBO0pjKfbsEISBqJxuCzJIr+0 +pIwMSdluQXxtyyqT3aXnoH9jl75dBDDvMEPR3c/I2+k9SWWoYslwhn2TqB94 +RFgwWpw/SH8+1b3lI1AWnkVpkkm8JOnteViHCz85ALd9xkACjq8UavPGLy0v +J6XRgsV1E2RTmydFB6vv/9w= +=quFc +-----END PGP SIGNATURE----- + From fb048a62f16afcb78da6f1fcaf560ced65f8e500 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:42:57 +0300 Subject: [PATCH 30/79] wip --- Core/source/test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/source/test.ts b/Core/source/test.ts index 8be27bbd6..ba98f073f 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -560,6 +560,10 @@ ava.default('can process dirty html without throwing', async t => { }); ava.default('verify encrypted+signed message by providing it correct public key', async t => { + const { keys } = getKeypairs('rsa1'); + const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true }, [await getCompatAsset('mime-email-plain-with-attachment')])); + console.log(blocks); + console.log(decryptJson); // TODO: implement the test t.pass(); }); From f69343f8f96e2897c79f9f47ad43826b82abe1d5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:46:08 +0300 Subject: [PATCH 31/79] wip --- Core/source/test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index ba98f073f..8436ebb9b 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -559,10 +559,11 @@ ava.default('can process dirty html without throwing', async t => { t.pass(); }); -ava.default('verify encrypted+signed message by providing it correct public key', async t => { +ava.default.only('verify encrypted+signed message by providing it correct public key', async t => { const { keys } = getKeypairs('rsa1'); - const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true }, [await getCompatAsset('mime-email-plain-with-attachment')])); + const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); console.log(blocks); + console.log('=========================='); console.log(decryptJson); // TODO: implement the test t.pass(); From 7c46aeeed9b7c09896d736ff6263050f322eba6d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 00:56:08 +0300 Subject: [PATCH 32/79] wip --- Core/source/test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 8436ebb9b..2854348fc 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -560,8 +560,8 @@ ava.default('can process dirty html without throwing', async t => { }); ava.default.only('verify encrypted+signed message by providing it correct public key', async t => { - const { keys } = getKeypairs('rsa1'); - const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + const { keys, pubKeys } = getKeypairs('rsa1'); + const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); console.log(blocks); console.log('=========================='); console.log(decryptJson); From 2ea2cbc42fc497cb71ee7a57b1df706cfc3bd062 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 01:04:58 +0300 Subject: [PATCH 33/79] wip --- Core/source/test.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 2854348fc..044ebc25c 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -559,22 +559,31 @@ ava.default('can process dirty html without throwing', async t => { t.pass(); }); -ava.default.only('verify encrypted+signed message by providing it correct public key', async t => { +ava.default('verify encrypted+signed message by providing it correct public key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); - const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); - console.log(blocks); - console.log('=========================='); + const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); console.log(decryptJson); // TODO: implement the test t.pass(); }); ava.default('verify encrypted+signed message by providing it one wrong and one correct', async t => { + const { keys, pubKeys } = getKeypairs('rsa1'); + const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); + const allPubKeys = []; + for (const pubkey of pubKeys2) allPubKeys.push(pubkey); + for (const pubkey of pubKeys) allPubKeys.push(pubkey); + const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + console.log(decryptJson); // TODO: implement the test t.pass(); }); -ava.default('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { +ava.default.only('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { + const { keys } = getKeypairs('rsa1'); + const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); + const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + console.log(decryptJson); // TODO: implement the test t.pass(); }); From 905e54a60184c246d9fc01e17434f1609947a469 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 22:02:31 +0300 Subject: [PATCH 34/79] wip --- Core/source/mobile-interface/endpoints.ts | 1 + Core/source/test.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index b547f7d66..f29881ce6 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -90,6 +90,7 @@ export class Endpoints { } else { rawBlocks.push(MsgBlock.fromContent('encryptedMsg', new Buf(Buf.concat(data)))); } + for (const block of rawBlocks) console.log('block type: ' + block.type); const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { diff --git a/Core/source/test.ts b/Core/source/test.ts index 044ebc25c..f55bed4ee 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -582,6 +582,8 @@ ava.default('verify encrypted+signed message by providing it one wrong and one c ava.default.only('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { const { keys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); + const msg = await getCompatAsset('mime-email-encrypted-inline-text-signed'); + console.log(msg.toString()); const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); console.log(decryptJson); // TODO: implement the test From 9e7ff9b7a3342a61e89d9be681dc85a77c70cd40 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 22:05:52 +0300 Subject: [PATCH 35/79] wip --- Core/source/mobile-interface/endpoints.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index f29881ce6..c36178fa9 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -90,7 +90,7 @@ export class Endpoints { } else { rawBlocks.push(MsgBlock.fromContent('encryptedMsg', new Buf(Buf.concat(data)))); } - for (const block of rawBlocks) console.log('block type: ' + block.type); + for (const block of rawBlocks) console.log('>>>> block type: ' + block.type); const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { @@ -102,6 +102,7 @@ export class Endpoints { } } else if (rawBlock.type === 'encryptedMsg' || rawBlock.type === 'signedMsg') { const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.content), verificationPubkeys }); + console.log(">>>> " + JSON.stringify(decryptRes)); if (decryptRes.success) { if (decryptRes.isEncrypted) { const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content); From e1100c222507d2fd7b07984b3b77245a4d541b9c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 22:07:19 +0300 Subject: [PATCH 36/79] wip --- ...ime-email-encrypted-inline-text-signed.txt | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt b/Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt index 1212c9177..739a49e1c 100644 --- a/Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt +++ b/Core/source/assets/compat/mime-email-encrypted-inline-text-signed.txt @@ -1,7 +1,7 @@ Delivered-To: flowcrypt.compatibility@gmail.com Return-Path: -Openpgp: id=6D24791A5B106262B06217C606CA553EC2455D70 -From: cryptup.tester@gmail.com +Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 +From: flowcrypt.compatibility@gmail.com MIME-Version: 1.0 Date: Thu, 2 Nov 2017 17:54:14 -0700 Message-ID: @@ -13,21 +13,21 @@ Content-Type: text/plain; charset="UTF-8" Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wcBMAwurnAGLJl0iAQf/Xu7ma7uF0HULsJctrcmSyzmsZ9HrBG6ITVs/Betd -0o6KVBnBYPrZYHN0Kkj/WlszRBUOapvA8gotXtXjTBYbRFGzL5PFuPGCxGzd -a1YYGAOyfk9VE8p0dZa6mCYEGJYGaCNoqh0xJKzdG2HNzCrY+samnA27nPXb -KZm51zMdKtL4iWc+RZ4P/lz4H0T58QHECNFK4S/aK4vtS8u9sAQma6jGoThY -PQqE4m3VYC8jRzQbdT+V584qKoAz8ELD/CMr1fwJep8RX23AR6psQno7XAnV -0sEGl8PLz9KiXp46UHcu3LNNcQihlADxB6iYvDqnF7KocTDUVQ19YhHJaOK5 -6NLAsgHYv0PGeUBLUcl5YRQqoQYW/Ryf/nOv0btEKQanjvsGQDnS/JtTr67J -L8egC4gtyA8Bz7+oS9a+p6d2Zk3ZhuPcqzEVzopBgnQaLfN2DlRZnhdqWoIB -0ofDHkn+R6Lx9oxANzRIFuT4xuxPnRknDhln+C3gTGpCSrM8amrqdng3IhGt -F7k0Xsax7AWZtkvKNaaeAQSf9A42YoiacTTZXHqVJUJbyMk2ryM9zEng0xyk -lLXIgBwVTXouM+D8kXWVDlpzwVksVw2jU/ITkyngou3X/ZKhBGPHd8VnMyni -r/slRzrvvzN525mljf0h0Ku49V+7xyFw45JmbrrW5soLS07PmpsmVBka4I8j -SReMsZrEPyZYpZStDpz0PPQv6qMijL4/gBB+wwjCl8eNmNV8ZZGvGcwgs972 -l45ijcVFaNdAmh5CXfCOnP8+GlNbIpkBywvPUZ4ZJB2BVY4U0wDjqJxbBIBP -NUZLDZ7yTlLeddP9kWA= -=NGUK +wcBMAwurnAGLJl0iAQf/Unn+k8dkJ35DM+jJPCqFYMyP9WY8J/2g4Kf5yvlR +7jarIe89D+Uu6nGJwKZXzQ/aLn1FQT6Y3ty+RxCB2hSNzkcrydE9vO0hGJde +0uK3cljgtiBTW1qDAKJAAD8y3i6CRrs4+mJacJCJ7XoQsZqvHzN/ywJ0/XDW +FEWINXtqrt7IyfIy9LbP4LsqifUZOX2SMQX5i8JMTO/85xJrgFpH429XvreG +BAD2NdxAA0zTuUKuJtdJGmRBN+aU/rRZTdu5sF8PfDtVBGmPTYuhIiCSCoGe +KwkxejyfkAPmeUqjiWXSUX0Tlulmfuogo0ofgtizhF5kww3IbE3tiH6fzIxU +RtLAsgFhC00k2WTu1jzunu6BCoHkhAghVAN8M3mF112e6wmeiS4y3cGGTAPi +g+C4cd223NzpiRc/BvauONUaL6LLJIcIC65eErU5Ii25X8AEXio7Juc9JT0Z +pwvAnVqOuxxIV+WCAi0QHerEPDNz5pl9uyiGwPSd8ecnr50zgiqLoT9RjzFs +PJJjijjkBV1fH72NBlJD5XwRNbRJZKGFonV1swZbd01Ki2D2ENQvgM+NN+r0 +Tdw/oauD+YfIxyc/mde3mF7ZDbBGmmATwvH1JyVURJKpXxT0SBKjkdeUYVL+ +wIxo5zvz8RNMbfz3AB9gH/VnlNdwLirFGgKe3feoBIuOH60KxrIOOO/zJhMs +eHHCiaIT9+73ML1murgnMJi0rhzopQp4q2CdkzrUZce8+NubyhMWyur6cA4p +adZoSa5urtIYvoDnFreNYpUPu6VGV2RBTTj6NPJjoGoCw3rSRNpzbHY1KnBf +O2iCZQZx7IYfqBeoJlI= +=ADUd -----END PGP MESSAGE----- From f9d32ff28db4b1582b0b64ea056ffc76da5b6024 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 22:32:33 +0300 Subject: [PATCH 37/79] wip --- Core/source/mobile-interface/endpoints.ts | 5 +++++ Core/source/test.ts | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index c36178fa9..4d048b9c5 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -106,6 +106,11 @@ export class Endpoints { if (decryptRes.success) { if (decryptRes.isEncrypted) { const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content); + if (decryptRes.signature) { + for (var block of formatted.blocks) { + block.verifyRes = decryptRes.signature; + } + } sequentialProcessedBlocks.push(...formatted.blocks); subject = formatted.subject || subject; } else { diff --git a/Core/source/test.ts b/Core/source/test.ts index f55bed4ee..522dae7fd 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -559,7 +559,7 @@ ava.default('can process dirty html without throwing', async t => { t.pass(); }); -ava.default('verify encrypted+signed message by providing it correct public key', async t => { +ava.default.only('verify encrypted+signed message by providing it correct public key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); console.log(decryptJson); @@ -579,7 +579,7 @@ ava.default('verify encrypted+signed message by providing it one wrong and one c t.pass(); }); -ava.default.only('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { +ava.default('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { const { keys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); const msg = await getCompatAsset('mime-email-encrypted-inline-text-signed'); From 8fa81f576f0b63c8c7c512f8757188190b243f36 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 22:44:33 +0300 Subject: [PATCH 38/79] wip --- Core/source/core/msg-block-parser.ts | 24 ++++++++++++++++------- Core/source/mobile-interface/endpoints.ts | 7 +------ Core/source/test.ts | 3 ++- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Core/source/core/msg-block-parser.ts b/Core/source/core/msg-block-parser.ts index aeef335d9..8249a9ef2 100644 --- a/Core/source/core/msg-block-parser.ts +++ b/Core/source/core/msg-block-parser.ts @@ -10,7 +10,7 @@ import { Catch } from '../platform/catch.js'; import { Mime } from './mime.js'; import { PgpArmor } from './pgp-armor.js'; import { PgpKey } from './pgp-key.js'; -import { PgpMsg } from './pgp-msg.js'; +import { PgpMsg, VerifyRes } from './pgp-msg.js'; import { Str } from './common.js'; type SanitizedBlocks = { blocks: MsgBlock[], subject: string | undefined, isRichText: boolean }; @@ -40,7 +40,7 @@ export class MsgBlockParser { } } - public static fmtDecryptedAsSanitizedHtmlBlocks = async (decryptedContent: Uint8Array, imgHandling: SanitizeImgHandling = 'IMG-TO-LINK'): Promise => { + public static fmtDecryptedAsSanitizedHtmlBlocks = async (decryptedContent: Uint8Array, signature?: VerifyRes, imgHandling: SanitizeImgHandling = 'IMG-TO-LINK'): Promise => { const blocks: MsgBlock[] = []; let isRichText = false; if (!Mime.resemblesMsg(decryptedContent)) { @@ -49,24 +49,34 @@ export class MsgBlockParser { utf = PgpMsg.stripFcTeplyToken(utf); const armoredPubKeys: string[] = []; utf = PgpMsg.stripPublicKeys(utf, armoredPubKeys); - blocks.push(MsgBlock.fromContent('decryptedHtml', Str.asEscapedHtml(utf))); // escaped text as html + const block = MsgBlock.fromContent('decryptedHtml', Str.asEscapedHtml(utf)); + block.verifyRes = signature; + blocks.push(block); // escaped text as html await MsgBlockParser.pushArmoredPubkeysToBlocks(armoredPubKeys, blocks); return { blocks, subject: undefined, isRichText }; } const decoded = await Mime.decode(decryptedContent); if (typeof decoded.html !== 'undefined') { - blocks.push(MsgBlock.fromContent('decryptedHtml', Xss.htmlSanitizeKeepBasicTags(decoded.html, imgHandling))); // sanitized html + const block = MsgBlock.fromContent('decryptedHtml', Xss.htmlSanitizeKeepBasicTags(decoded.html, imgHandling)); + block.verifyRes = signature; + blocks.push(block); // sanitized html isRichText = true; } else if (typeof decoded.text !== 'undefined') { - blocks.push(MsgBlock.fromContent('decryptedHtml', Str.asEscapedHtml(decoded.text))); // escaped text as html + const block = MsgBlock.fromContent('decryptedHtml', Str.asEscapedHtml(decoded.text)); + block.verifyRes = signature; + blocks.push(block); // escaped text as html } else { - blocks.push(MsgBlock.fromContent('decryptedHtml', Str.asEscapedHtml(Buf.with(decryptedContent).toUtfStr()))); // escaped mime text as html + const block = MsgBlock.fromContent('decryptedHtml', Str.asEscapedHtml(Buf.with(decryptedContent).toUtfStr())); + block.verifyRes = signature; + blocks.push(); // escaped mime text as html } for (const att of decoded.atts) { if (att.treatAs() === 'publicKey') { await MsgBlockParser.pushArmoredPubkeysToBlocks([att.getData().toUtfStr()], blocks); } else { - blocks.push(MsgBlock.fromAtt('decryptedAtt', '', { name: att.name, data: att.getData(), length: att.length, type: att.type })); + const block = MsgBlock.fromAtt('decryptedAtt', '', { name: att.name, data: att.getData(), length: att.length, type: att.type }); + block.verifyRes = signature; + blocks.push(block); } } return { blocks, subject: decoded.subject, isRichText }; diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 4d048b9c5..f9ce8febe 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -105,12 +105,7 @@ export class Endpoints { console.log(">>>> " + JSON.stringify(decryptRes)); if (decryptRes.success) { if (decryptRes.isEncrypted) { - const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content); - if (decryptRes.signature) { - for (var block of formatted.blocks) { - block.verifyRes = decryptRes.signature; - } - } + const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content, decryptRes.signature); sequentialProcessedBlocks.push(...formatted.blocks); subject = formatted.subject || subject; } else { diff --git a/Core/source/test.ts b/Core/source/test.ts index 522dae7fd..0c868d5c5 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -561,8 +561,9 @@ ava.default('can process dirty html without throwing', async t => { ava.default.only('verify encrypted+signed message by providing it correct public key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); - const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); console.log(decryptJson); + console.log(decryptData.toString()); // TODO: implement the test t.pass(); }); From fd696b5d98272d93a6d70abe1f1acff8cbaf44a8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 22:48:40 +0300 Subject: [PATCH 39/79] wip --- Core/source/mobile-interface/endpoints.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index f9ce8febe..7d676cdca 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -136,12 +136,15 @@ export class Endpoints { sequentialProcessedBlocks.push(rawBlock); } } + // At this point we have sequentialProcessedBlocks filled const msgContentBlocks: MsgBlock[] = []; const blocks: MsgBlock[] = []; let replyType = 'plain'; for (const block of sequentialProcessedBlocks) { // fix/adjust/format blocks before returning it over JSON if (block.content instanceof Buf) { // cannot JSON-serialize Buf - block.content = isContentBlock(block.type) ? block.content.toUtfStr() : block.content.toRawBytesStr(); + block.content = isContentBlock(block.type) + ? block.content.toUtfStr() + : block.content.toRawBytesStr(); } else if (block.attMeta && block.attMeta.data instanceof Uint8Array) { // converting to base64-encoded string instead of uint8 for JSON serilization // value actually replaced to a string, but type remains Uint8Array type set to satisfy TS From 53f26e53f8ba46be714be028bffb6fa4379f7912 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 22:54:15 +0300 Subject: [PATCH 40/79] wip --- Core/source/mobile-interface/format-output.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/source/mobile-interface/format-output.ts b/Core/source/mobile-interface/format-output.ts index 461c8204d..4d04cc2d7 100644 --- a/Core/source/mobile-interface/format-output.ts +++ b/Core/source/mobile-interface/format-output.ts @@ -8,6 +8,7 @@ import { Buf } from '../core/buf'; import { Mime } from '../core/mime'; import { Str } from '../core/common'; import { Xss } from '../platform/xss'; +import { VerifyRes } from '../core/pgp-msg'; export type Buffers = (Buf | Uint8Array)[]; export type EndpointRes = {json: string, data: Buf | Uint8Array}; @@ -71,7 +72,9 @@ export const fmtContentBlock = (allContentBlocks: MsgBlock[]): { contentBlock: M imgsAtTheBottom.push(plainImgBlock); } } + var verifyRes: (VerifyRes | undefined) = undefined; for (const block of contentBlocks) { + if (!verifyRes && block.verifyRes) verifyRes = block.verifyRes; if (block.type === 'decryptedText') { msgContentAsHtml += fmtMsgContentBlockAsHtml(Str.asEscapedHtml(block.content.toString()), 'green'); msgContentAsText += block.content.toString() + '\n'; @@ -114,7 +117,9 @@ export const fmtContentBlock = (allContentBlocks: MsgBlock[]): { contentBlock: M ${msgContentAsHtml} `; - return { contentBlock: MsgBlock.fromContent('plainHtml', msgContentAsHtml), text: msgContentAsText.trim() }; + const contentBlock = MsgBlock.fromContent('plainHtml', msgContentAsHtml); + contentBlock.verifyRes = verifyRes; + return { contentBlock: contentBlock, text: msgContentAsText.trim() }; } export const fmtRes = (response: {}, data?: Buf | Uint8Array): EndpointRes => { From 61ed2745402dfb76227c212a9ac67d37601f5ee8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:05:22 +0300 Subject: [PATCH 41/79] wip --- Core/source/test.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 0c868d5c5..db10e9732 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -562,9 +562,11 @@ ava.default('can process dirty html without throwing', async t => { ava.default.only('verify encrypted+signed message by providing it correct public key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); - console.log(decryptJson); - console.log(decryptData.toString()); - // TODO: implement the test + expect(decryptJson.replyType).equals('encrypted'); + expect(decryptJson.subject).equals('mime email encrypted inline text signed'); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(true); t.pass(); }); @@ -574,9 +576,12 @@ ava.default('verify encrypted+signed message by providing it one wrong and one c const allPubKeys = []; for (const pubkey of pubKeys2) allPubKeys.push(pubkey); for (const pubkey of pubKeys) allPubKeys.push(pubkey); - const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); - console.log(decryptJson); - // TODO: implement the test + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + expect(decryptJson.replyType).equals('encrypted'); + expect(decryptJson.subject).equals('mime email encrypted inline text signed'); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(true); t.pass(); }); @@ -585,9 +590,12 @@ ava.default('verify encrypted+signed message by providing it only a wrong public const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); const msg = await getCompatAsset('mime-email-encrypted-inline-text-signed'); console.log(msg.toString()); - const { json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); - console.log(decryptJson); - // TODO: implement the test + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + expect(decryptJson.replyType).equals('encrypted'); + expect(decryptJson.subject).equals('mime email encrypted inline text signed'); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(null); t.pass(); }); From 5531b9d12bb29daa6f3582c83d599057eb382137 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:06:40 +0300 Subject: [PATCH 42/79] wip --- Core/source/mobile-interface/endpoints.ts | 4 ++-- Core/source/test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 7d676cdca..4abc0580b 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -90,7 +90,7 @@ export class Endpoints { } else { rawBlocks.push(MsgBlock.fromContent('encryptedMsg', new Buf(Buf.concat(data)))); } - for (const block of rawBlocks) console.log('>>>> block type: ' + block.type); + // for (const block of rawBlocks) console.log('>>>> block type: ' + block.type); const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { @@ -102,7 +102,7 @@ export class Endpoints { } } else if (rawBlock.type === 'encryptedMsg' || rawBlock.type === 'signedMsg') { const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.content), verificationPubkeys }); - console.log(">>>> " + JSON.stringify(decryptRes)); + // console.log(">>>> " + JSON.stringify(decryptRes)); if (decryptRes.success) { if (decryptRes.isEncrypted) { const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content, decryptRes.signature); diff --git a/Core/source/test.ts b/Core/source/test.ts index db10e9732..9c554ee64 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -559,7 +559,7 @@ ava.default('can process dirty html without throwing', async t => { t.pass(); }); -ava.default.only('verify encrypted+signed message by providing it correct public key', async t => { +ava.default('verify encrypted+signed message by providing it correct public key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); expect(decryptJson.replyType).equals('encrypted'); @@ -570,7 +570,7 @@ ava.default.only('verify encrypted+signed message by providing it correct public t.pass(); }); -ava.default('verify encrypted+signed message by providing it one wrong and one correct', async t => { +ava.default.only('verify encrypted+signed message by providing it one wrong and one correct', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); const allPubKeys = []; From 6c8565968ff71ea811ad36371e1af66b9a71ca18 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:11:52 +0300 Subject: [PATCH 43/79] wip --- Core/source/test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 9c554ee64..f89bc6013 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -570,7 +570,7 @@ ava.default('verify encrypted+signed message by providing it correct public key' t.pass(); }); -ava.default.only('verify encrypted+signed message by providing it one wrong and one correct', async t => { +ava.default('verify encrypted+signed message by providing it one wrong and one correct', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); const allPubKeys = []; @@ -585,11 +585,9 @@ ava.default.only('verify encrypted+signed message by providing it one wrong and t.pass(); }); -ava.default('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { +ava.default.only('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { const { keys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); - const msg = await getCompatAsset('mime-email-encrypted-inline-text-signed'); - console.log(msg.toString()); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); expect(decryptJson.replyType).equals('encrypted'); expect(decryptJson.subject).equals('mime email encrypted inline text signed'); From 634d631b4b97753d2f6f1cc46b546845f97c8af7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:30:27 +0300 Subject: [PATCH 44/79] wip --- Core/source/test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index f89bc6013..1c6a5c773 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -585,7 +585,7 @@ ava.default('verify encrypted+signed message by providing it one wrong and one c t.pass(); }); -ava.default.only('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { +ava.default('verify encrypted+signed message by providing it only a wrong public key (fail: cannot verify)', async t => { const { keys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); @@ -597,8 +597,12 @@ ava.default.only('verify encrypted+signed message by providing it only a wrong p t.pass(); }); -ava.default('verify plain-text signed message by providing it correct key', async t => { - // TODO: implement the test +ava.default.only('verify plain-text signed message by providing it correct key', async t => { + const { keys, pubKeys } = getKeypairs('rsa1'); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed')])); + expect(decryptJson.replyType).equals('plain'); + expect(decryptJson.subject).equals('mime email plain signed'); + console.log(decryptData.toString()); t.pass(); }); From 2ec9fcbbda3568a06ba47a6b5fd0badfe963bc73 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:34:40 +0300 Subject: [PATCH 45/79] wip --- Core/source/test.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 1c6a5c773..be6f8b762 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -597,12 +597,30 @@ ava.default('verify encrypted+signed message by providing it only a wrong public t.pass(); }); -ava.default.only('verify plain-text signed message by providing it correct key', async t => { +ava.default('verify plain-text signed message by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); console.log(decryptData.toString()); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(true); + t.pass(); +}); + +ava.default.only('verify plain-text signed message by providing it both correct and incorrect keys', async t => { + const { keys, pubKeys } = getKeypairs('rsa1'); + const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); + const allPubKeys = []; + for (const pubkey of pubKeys2) allPubKeys.push(pubkey); + for (const pubkey of pubKeys) allPubKeys.push(pubkey); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + expect(decryptJson.replyType).equals('plain'); + expect(decryptJson.subject).equals('mime email plain signed'); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(true); t.pass(); }); From eda1a70d259cd8bba0e2dd37744bf08dc058edd1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:36:57 +0300 Subject: [PATCH 46/79] wip --- Core/source/test.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index be6f8b762..6d615a1ef 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -609,13 +609,13 @@ ava.default('verify plain-text signed message by providing it correct key', asyn t.pass(); }); -ava.default.only('verify plain-text signed message by providing it both correct and incorrect keys', async t => { +ava.default('verify plain-text signed message by providing it both correct and incorrect keys', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); const allPubKeys = []; for (const pubkey of pubKeys2) allPubKeys.push(pubkey); for (const pubkey of pubKeys) allPubKeys.push(pubkey); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-encrypted-inline-text-signed')])); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); const parsedDecryptData = JSON.parse(decryptData.toString()); @@ -624,8 +624,15 @@ ava.default.only('verify plain-text signed message by providing it both correct t.pass(); }); -ava.default('verify plain-text signed message by providing it wrong key (fail: cannot verify)', async t => { - // TODO: implement the test +ava.default.only('verify plain-text signed message by providing it wrong key (fail: cannot verify)', async t => { + const { keys } = getKeypairs('rsa1'); + const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-plain-signed')])); + expect(decryptJson.replyType).equals('plain'); + expect(decryptJson.subject).equals('mime email plain signed'); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(null); t.pass(); }); From ed87c97e96254f7d01bd218a9a5be23f9ff53fa8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:39:45 +0300 Subject: [PATCH 47/79] wip --- .../compat/mime-email-plain-signed-edited.txt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Core/source/assets/compat/mime-email-plain-signed-edited.txt diff --git a/Core/source/assets/compat/mime-email-plain-signed-edited.txt b/Core/source/assets/compat/mime-email-plain-signed-edited.txt new file mode 100644 index 000000000..a1a58d969 --- /dev/null +++ b/Core/source/assets/compat/mime-email-plain-signed-edited.txt @@ -0,0 +1,32 @@ +Delivered-To: flowcrypt.compatibility@gmail.com +Return-Path: +Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 +From: flowcrypt.compatibility@gmail.com +MIME-Version: 1.0 +Date: Thu, 2 Nov 2017 17:54:14 -0700 +Message-ID: +Subject: mime email plain signed +To: flowcrypt.compatibility@gmail.com +Content-Type: text/plain; charset="UTF-8" + + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +some +汉 +TXT +-----BEGIN PGP SIGNATURE----- +Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption +Comment: Seamlessly send and receive encrypted email + +wsBcBAEBCAAGBQJhY1x0AAoJEDow9MwKmo8QMR0H/iHkHFr1doJhqIVsSXyQ +bBwYpoaIRHEZlF3RQa3sbkLqXSTzHf81ySb7/oXgd+z5RYYw2vD9bebaInb3 +Ca9FuBrM4ZlnmVVnNpv/nntZZdln+AVq+rEOaLDcHC4nFTC3Z7QwulZn31Hm +b0JcsGAuIDfUZ1mFfFpyCq7KB+XGbV3bc+bUBO0pjKfbsEISBqJxuCzJIr+0 +pIwMSdluQXxtyyqT3aXnoH9jl75dBDDvMEPR3c/I2+k9SWWoYslwhn2TqB94 +RFgwWpw/SH8+1b3lI1AWnkVpkkm8JOnteViHCz85ALd9xkACjq8UavPGLy0v +J6XRgsV1E2RTmydFB6vv/9w= +=quFc +-----END PGP SIGNATURE----- + From 6841e195abc926d588be969bf466af5764c28dbd Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:42:27 +0300 Subject: [PATCH 48/79] wip --- Core/source/test.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 6d615a1ef..1db099c56 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -624,7 +624,7 @@ ava.default('verify plain-text signed message by providing it both correct and i t.pass(); }); -ava.default.only('verify plain-text signed message by providing it wrong key (fail: cannot verify)', async t => { +ava.default('verify plain-text signed message by providing it wrong key (fail: cannot verify)', async t => { const { keys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-plain-signed')])); @@ -636,8 +636,15 @@ ava.default.only('verify plain-text signed message by providing it wrong key (fa t.pass(); }); -ava.default('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { - // TODO: implement the test +ava.default.only('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { + const { keys, pubKeys } = getKeypairs('rsa1'); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-edited')])); + expect(decryptJson.replyType).equals('plain'); + expect(decryptJson.subject).equals('mime email plain signed'); + console.log(decryptData.toString()); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(null); t.pass(); }); From 702ad15913ab17d1a5203adb9255260755d8d852 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:43:21 +0300 Subject: [PATCH 49/79] wip --- Core/source/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 1db099c56..c3a99ec40 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -644,7 +644,7 @@ ava.default.only('verify plain-text signed message that you edited after signing console.log(decryptData.toString()); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); - expect(parsedDecryptData.verifyRes.match).equals(null); + expect(parsedDecryptData.verifyRes.match).equals(false); t.pass(); }); From 95507a0a523a86900cf683f00555e80e94805945 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:44:42 +0300 Subject: [PATCH 50/79] wip --- Core/source/mobile-interface/endpoints.ts | 2 -- Core/source/test.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 4abc0580b..6328106b9 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -90,7 +90,6 @@ export class Endpoints { } else { rawBlocks.push(MsgBlock.fromContent('encryptedMsg', new Buf(Buf.concat(data)))); } - // for (const block of rawBlocks) console.log('>>>> block type: ' + block.type); const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { @@ -102,7 +101,6 @@ export class Endpoints { } } else if (rawBlock.type === 'encryptedMsg' || rawBlock.type === 'signedMsg') { const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.content), verificationPubkeys }); - // console.log(">>>> " + JSON.stringify(decryptRes)); if (decryptRes.success) { if (decryptRes.isEncrypted) { const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content, decryptRes.signature); diff --git a/Core/source/test.ts b/Core/source/test.ts index c3a99ec40..5931c284a 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -602,7 +602,6 @@ ava.default('verify plain-text signed message by providing it correct key', asyn const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); - console.log(decryptData.toString()); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); expect(parsedDecryptData.verifyRes.match).equals(true); @@ -641,7 +640,6 @@ ava.default.only('verify plain-text signed message that you edited after signing const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-edited')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); - console.log(decryptData.toString()); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); expect(parsedDecryptData.verifyRes.match).equals(false); From 334166eea627f15cf7e8e635a7cc6ba59fddad00 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:45:20 +0300 Subject: [PATCH 51/79] wip --- Core/source/test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 5931c284a..1a15c0a93 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -647,6 +647,12 @@ ava.default.only('verify plain-text signed message that you edited after signing }); ava.default('verify signed message with detached signature by providing it correct key', async t => { - // TODO: implement the test + const { keys, pubKeys } = getKeypairs('rsa1'); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); + expect(decryptJson.replyType).equals('plain'); + expect(decryptJson.subject).equals('mime email plain signed'); + const parsedDecryptData = JSON.parse(decryptData.toString()); + expect(!!parsedDecryptData.verifyRes).equals(true); + expect(parsedDecryptData.verifyRes.match).equals(true); t.pass(); }); From f59f4a852fb9b6bbf0b48eea3c52c16f0123fde7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:45:40 +0300 Subject: [PATCH 52/79] wip --- Core/source/test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 1a15c0a93..ed28b786c 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -635,7 +635,7 @@ ava.default('verify plain-text signed message by providing it wrong key (fail: c t.pass(); }); -ava.default.only('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { +ava.default('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-edited')])); expect(decryptJson.replyType).equals('plain'); @@ -646,7 +646,7 @@ ava.default.only('verify plain-text signed message that you edited after signing t.pass(); }); -ava.default('verify signed message with detached signature by providing it correct key', async t => { +ava.default.only('verify signed message with detached signature by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); expect(decryptJson.replyType).equals('plain'); From dafb06c8cef79bec9d578f07dc48b54c921cc199 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:51:27 +0300 Subject: [PATCH 53/79] wip --- Core/source/core/pgp-msg.ts | 10 +++++++--- Core/source/mobile-interface/endpoints.ts | 2 +- Core/source/test.ts | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 0d512b4dc..80d20c10c 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -21,7 +21,7 @@ export namespace PgpMsgMethod { export type Type = { data: Uint8Array }; export type Decrypt = { kisWithPp: PrvKeyInfo[], encryptedData: Uint8Array, msgPwd?: string, verificationPubkeys?: string[] }; export type DiagnosePubkeys = { privateKis: KeyInfo[], message: Uint8Array }; - export type VerifyDetached = { plaintext: Uint8Array, sigText: Uint8Array }; + export type VerifyDetached = { plaintext: Uint8Array, sigText: Uint8Array, verificationPubkeys?: string[] }; } export type DiagnosePubkeys = (arg: Arg.DiagnosePubkeys) => Promise; export type VerifyDetached = (arg: Arg.VerifyDetached) => Promise; @@ -151,11 +151,15 @@ export class PgpMsg { return sig; } - public static verifyDetached: PgpMsgMethod.VerifyDetached = async ({ plaintext, sigText }) => { + public static verifyDetached: PgpMsgMethod.VerifyDetached = async ({ plaintext, sigText, verificationPubkeys }) => { const message = openpgp.message.fromText(Buf.fromUint8(plaintext).toUtfStr()); await message.appendSignature(Buf.fromUint8(sigText).toUtfStr()); - // Q: Should we add verificationPubkeys here????? const keys = await PgpMsg.getSortedKeys([], message); + if (verificationPubkeys) { + for (const verificationPubkey of verificationPubkeys) { + keys.forVerification.push(...(await openpgp.key.readArmored(verificationPubkey)).keys); + } + } return await PgpMsg.verify(message, keys.forVerification); } diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 6328106b9..e911307b1 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -93,7 +93,7 @@ export class Endpoints { const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { - const verify = await PgpMsg.verifyDetached({ sigText: Buf.fromUtfStr(rawBlock.signature), plaintext: Buf.with(rawSigned || rawBlock.content) }); + const verify = await PgpMsg.verifyDetached({ sigText: Buf.fromUtfStr(rawBlock.signature), plaintext: Buf.with(rawSigned || rawBlock.content), verificationPubkeys: verificationPubkeys }); if (rawBlock.type === 'signedHtml') { sequentialProcessedBlocks.push({ type: 'verifiedMsg', content: Xss.htmlSanitizeKeepBasicTags(rawBlock.content.toString()), verifyRes: verify, complete: true }); } else { // text diff --git a/Core/source/test.ts b/Core/source/test.ts index ed28b786c..8e7c109ae 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -650,7 +650,7 @@ ava.default.only('verify signed message with detached signature by providing it const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); expect(decryptJson.replyType).equals('plain'); - expect(decryptJson.subject).equals('mime email plain signed'); + expect(decryptJson.subject).equals('mime email plain signed detached'); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); expect(parsedDecryptData.verifyRes.match).equals(true); From 24f427c57485dd768fcd6604cff1a77506dc38ba Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:52:58 +0300 Subject: [PATCH 54/79] wip --- Core/source/test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/source/test.ts b/Core/source/test.ts index 8e7c109ae..774236e95 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -651,6 +651,7 @@ ava.default.only('verify signed message with detached signature by providing it const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed detached'); + console.log(decryptData.toString()); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); expect(parsedDecryptData.verifyRes.match).equals(true); From e99d9656a6568879dffe46f4c59c74984869b30d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 11 Oct 2021 23:58:35 +0300 Subject: [PATCH 55/79] wip --- Core/source/mobile-interface/endpoints.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index e911307b1..6ab637d37 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -90,6 +90,7 @@ export class Endpoints { } else { rawBlocks.push(MsgBlock.fromContent('encryptedMsg', new Buf(Buf.concat(data)))); } + for (const rawBlock of rawBlocks) console.log(JSON.stringify(rawBlock) + '\n'); const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { From 1a8797f7d636479618922b2786e19f9a6a38fb1c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 00:06:45 +0300 Subject: [PATCH 56/79] wip --- Core/source/gen-compat-assets.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 4bfba304f..934dec8f4 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -88,7 +88,9 @@ ${text.toString()} `.replace(/^\n/, '')); // Used to generate encrypted+signed and plaintext signed emails -const mimeEmail2 = (t: AvaContext, text: Buffer | string) => Buffer.from(` +const mimeEmail2 = (t: AvaContext, text1: Buffer | string, text2?: Buffer | string) => { + const t2 = text2 ? '\n' + text2.toString() : ''; + return Buffer.from(` Delivered-To: flowcrypt.compatibility@gmail.com Return-Path: Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 @@ -100,8 +102,9 @@ Subject: ${subject(t)} To: flowcrypt.compatibility@gmail.com Content-Type: text/plain; charset="UTF-8" -${text.toString()} +${text1.toString()}${t2} `.replace(/^\n/, '')); +} const mimePgp = (t: AvaContext, text: string | Buffer) => Buffer.from(` Content-Type: multipart/mixed; boundary="PpujspXwR9sayhr0t4sBaTxoXX6dlYhLU"; From dd80785cdc821145eb49d7b4dce8ceccab49b43d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 00:14:18 +0300 Subject: [PATCH 57/79] wip --- .../mime-email-plain-signed-detached.txt | 20 +++++++++++-------- Core/source/gen-compat-assets.ts | 8 ++++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached.txt b/Core/source/assets/compat/mime-email-plain-signed-detached.txt index 4e9411dc1..ca1fb861e 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached.txt @@ -9,17 +9,21 @@ Subject: mime email plain signed detached To: flowcrypt.compatibility@gmail.com Content-Type: text/plain; charset="UTF-8" +some +汉 +txt + -----BEGIN PGP SIGNATURE----- Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wsBcBAEBCAAGBQJhY1x0AAoJEDow9MwKmo8QMR0H/iHkHFr1doJhqIVsSXyQ -bBwYpoaIRHEZlF3RQa3sbkLqXSTzHf81ySb7/oXgd+z5RYYw2vD9bebaInb3 -Ca9FuBrM4ZlnmVVnNpv/nntZZdln+AVq+rEOaLDcHC4nFTC3Z7QwulZn31Hm -b0JcsGAuIDfUZ1mFfFpyCq7KB+XGbV3bc+bUBO0pjKfbsEISBqJxuCzJIr+0 -pIwMSdluQXxtyyqT3aXnoH9jl75dBDDvMEPR3c/I2+k9SWWoYslwhn2TqB94 -RFgwWpw/SH8+1b3lI1AWnkVpkkm8JOnteViHCz85ALd9xkACjq8UavPGLy0v -J6XRgsV1E2RTmydFB6vv/9w= -=quFc +wsBcBAEBCAAGBQJhZKj9AAoJEDow9MwKmo8Q9GAH/0VkC/MbhTkCjpvQ0PVQ +WVd+/lpDyOzB/6paHdY7aKeSSlXF9W5t3G3R+azv41WLW+J9J/wrh3TNtMWl +WA7Wz0VSzjp0CbJDNh67IeyooT1rQ98IADXD8zQk5lv2MogzaKqjjhenWRYD +YXDmfYzrj9pPa/p7qombWtiKxNLS16mTubd/ae2NSIAN6P0q5NipMbyBw+Wc +jnZroTErhZrVgQRNQRfODI8uIkA6gU2lff5742jAZEWhQDIREPTNqgoC3OiY +HDTk4LlG1eavKJLCyHFRdO6BOStf5fDwh+04BZtwzfRs48svg69Iza9L+IMX +GMKMMBmjDsQlzYUf6S+3WZ0= +=XKCS -----END PGP SIGNATURE----- diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 934dec8f4..3e09ea2f8 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -88,8 +88,8 @@ ${text.toString()} `.replace(/^\n/, '')); // Used to generate encrypted+signed and plaintext signed emails -const mimeEmail2 = (t: AvaContext, text1: Buffer | string, text2?: Buffer | string) => { - const t2 = text2 ? '\n' + text2.toString() : ''; +const mimeEmail2 = (t: AvaContext, text1: Buffer | string, original?: Buffer | string) => { + const orig = original ? original.toString() + '\n\n' : ''; return Buffer.from(` Delivered-To: flowcrypt.compatibility@gmail.com Return-Path: @@ -102,7 +102,7 @@ Subject: ${subject(t)} To: flowcrypt.compatibility@gmail.com Content-Type: text/plain; charset="UTF-8" -${text1.toString()}${t2} +${orig}${text1.toString()} `.replace(/^\n/, '')); } @@ -228,6 +228,6 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const data = text.toString(); const signed = await PgpMsg.sign(signingPrv, data, true); - await write(t, mimeEmail2(t, signed)); + await write(t, mimeEmail2(t, signed, data)); t.pass(); }); From a3991816d3c41d3b3f0ee46e8b88be6d0ad24f91 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 00:26:56 +0300 Subject: [PATCH 58/79] wip --- Core/source/gen-compat-assets.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 3e09ea2f8..7e909441e 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -88,7 +88,7 @@ ${text.toString()} `.replace(/^\n/, '')); // Used to generate encrypted+signed and plaintext signed emails -const mimeEmail2 = (t: AvaContext, text1: Buffer | string, original?: Buffer | string) => { +const mimeEmail2 = (t: AvaContext, text: Buffer | string, original?: Buffer | string) => { const orig = original ? original.toString() + '\n\n' : ''; return Buffer.from(` Delivered-To: flowcrypt.compatibility@gmail.com @@ -102,7 +102,7 @@ Subject: ${subject(t)} To: flowcrypt.compatibility@gmail.com Content-Type: text/plain; charset="UTF-8" -${orig}${text1.toString()} +${orig}${text.toString()} `.replace(/^\n/, '')); } From c0594e0af8eb2e44e615b3eff5ad6dc1cf2da61d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 21:41:09 +0300 Subject: [PATCH 59/79] wip --- .../mime-email-plain-signed-detached2.txt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Core/source/assets/compat/mime-email-plain-signed-detached2.txt diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt new file mode 100644 index 000000000..6577731f6 --- /dev/null +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -0,0 +1,32 @@ +Delivered-To: flowcrypt.compatibility@gmail.com +Return-Path: +Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 +From: flowcrypt.compatibility@gmail.com +MIME-Version: 1.0 +Date: Thu, 2 Nov 2017 17:54:14 -0700 +Message-ID: +Subject: mime email plain signed detached +To: flowcrypt.compatibility@gmail.com +Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; +boundary="UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy" + +--2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen +Content-Type: multipart/mixed; boundary="------------318DB2E1763BE977A4E99886" +Content-Language: en-US + +--------------318DB2E1763BE977A4E99886 +Content-Type: text/plain; charset=utf-8; format=flowed +Content-Transfer-Encoding: quoted-printable + +This is plaintext with detached signature + + +--------------318DB2E1763BE977A4E99886-- +--2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen-- +--UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy +Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" +Content-Description: OpenPGP digital signature +Content-Disposition: attachment; filename="OpenPGP_signature" + + +--UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy-- From ea9a962a1b86043c559fba0c5f94792016f484df Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 21:50:45 +0300 Subject: [PATCH 60/79] wip --- Core/source/gen-compat-assets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 7e909441e..7aa6fabc3 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -226,7 +226,7 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - const data = text.toString(); + const data = "some text"; const signed = await PgpMsg.sign(signingPrv, data, true); await write(t, mimeEmail2(t, signed, data)); t.pass(); From a6f748e625762e74914d08c16ca7773816d99d1d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 21:51:15 +0300 Subject: [PATCH 61/79] wip --- .../mime-email-plain-signed-detached.txt | 20 +++++------ .../mime-email-plain-signed-detached2.txt | 35 ++++++++++++++++--- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached.txt b/Core/source/assets/compat/mime-email-plain-signed-detached.txt index ca1fb861e..2f060245b 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached.txt @@ -9,21 +9,19 @@ Subject: mime email plain signed detached To: flowcrypt.compatibility@gmail.com Content-Type: text/plain; charset="UTF-8" -some -汉 -txt +some text -----BEGIN PGP SIGNATURE----- Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wsBcBAEBCAAGBQJhZKj9AAoJEDow9MwKmo8Q9GAH/0VkC/MbhTkCjpvQ0PVQ -WVd+/lpDyOzB/6paHdY7aKeSSlXF9W5t3G3R+azv41WLW+J9J/wrh3TNtMWl -WA7Wz0VSzjp0CbJDNh67IeyooT1rQ98IADXD8zQk5lv2MogzaKqjjhenWRYD -YXDmfYzrj9pPa/p7qombWtiKxNLS16mTubd/ae2NSIAN6P0q5NipMbyBw+Wc -jnZroTErhZrVgQRNQRfODI8uIkA6gU2lff5742jAZEWhQDIREPTNqgoC3OiY -HDTk4LlG1eavKJLCyHFRdO6BOStf5fDwh+04BZtwzfRs48svg69Iza9L+IMX -GMKMMBmjDsQlzYUf6S+3WZ0= -=XKCS +wsBcBAEBCAAGBQJhZddKAAoJEDow9MwKmo8QN04H/AgF1juV59IGlifqcw1b +pIbL7Wy2RGN3HRf71EKIQxq7Aw915MUS5KwJ71ip/BqBJs9UF7PvYJ3czwiv +Wp1Q/cihblMfpJaZyp1AC0shu6WAPZv6VE7Pk0eJ9AduYsQEifGQZPBQWnnN +E0mi1gUk/nTeXbAgf475sKjkZrWa02H8IC5LBKbew0smhjA/2BpkPJDFaWRS +WrQZr3kq4/ErIBCtFnnWx2k5ONNbsBi8mhWhI3Mr+us6JCYfrUiffpR39pBS +1OPOx4IAu1pJiZE7QWNJq77ldO0Sbdgq4J97wGmnSbb/0zTUwF6moGxgDJur +JqSoBWuMilggHft/Taq2HN8= +=ARBb -----END PGP SIGNATURE----- diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index 6577731f6..e25684d06 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -7,26 +7,51 @@ Date: Thu, 2 Nov 2017 17:54:14 -0700 Message-ID: Subject: mime email plain signed detached To: flowcrypt.compatibility@gmail.com -Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; -boundary="UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy" +Content-Type: multipart/signed; micalg=pgp-sha256; + protocol="application/pgp-signature"; + boundary="UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy" + +This is an OpenPGP/MIME signed message (RFC 4880 and 3156) +--UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy +Content-Type: multipart/mixed; boundary="2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen"; + protected-headers="v1" +From: Perpetuum Moobilee +To: flowcrypt.compatibility@gmail.com +Message-ID: +Subject: plaintext with detached signature --2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen -Content-Type: multipart/mixed; boundary="------------318DB2E1763BE977A4E99886" +Content-Type: multipart/mixed; + boundary="------------318DB2E1763BE977A4E99886" Content-Language: en-US +This is a multi-part message in MIME format. --------------318DB2E1763BE977A4E99886 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable -This is plaintext with detached signature +some text ---------------318DB2E1763BE977A4E99886-- --2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen-- + --UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="OpenPGP_signature" +-----BEGIN PGP SIGNATURE----- +Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption +Comment: Seamlessly send and receive encrypted email + +wsBcBAEBCAAGBQJhZddKAAoJEDow9MwKmo8QN04H/AgF1juV59IGlifqcw1b +pIbL7Wy2RGN3HRf71EKIQxq7Aw915MUS5KwJ71ip/BqBJs9UF7PvYJ3czwiv +Wp1Q/cihblMfpJaZyp1AC0shu6WAPZv6VE7Pk0eJ9AduYsQEifGQZPBQWnnN +E0mi1gUk/nTeXbAgf475sKjkZrWa02H8IC5LBKbew0smhjA/2BpkPJDFaWRS +WrQZr3kq4/ErIBCtFnnWx2k5ONNbsBi8mhWhI3Mr+us6JCYfrUiffpR39pBS +1OPOx4IAu1pJiZE7QWNJq77ldO0Sbdgq4J97wGmnSbb/0zTUwF6moGxgDJur +JqSoBWuMilggHft/Taq2HN8= +=ARBb +-----END PGP SIGNATURE----- --UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy-- From 52dd244050c679f04d73475ddf6c7783f1b5726b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 22:26:55 +0300 Subject: [PATCH 62/79] wip --- .../mime-email-plain-signed-detached2.txt | 75 ++++++++++--------- Core/source/test.ts | 2 +- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index e25684d06..e52299316 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -1,57 +1,58 @@ -Delivered-To: flowcrypt.compatibility@gmail.com Return-Path: -Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 -From: flowcrypt.compatibility@gmail.com -MIME-Version: 1.0 -Date: Thu, 2 Nov 2017 17:54:14 -0700 -Message-ID: -Subject: mime email plain signed detached +Received: from [192.168.88.243] ([176.100.5.125]) + by smtp.gmail.com with ESMTPSA id q7sm1107487lfc.159.2021.10.12.12.25.56 + for + (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); + Tue, 12 Oct 2021 12:25:57 -0700 (PDT) To: flowcrypt.compatibility@gmail.com +From: Flowcrypt Compatibility +Subject: mime email plain signed detached +Message-ID: +Date: Tue, 12 Oct 2021 22:25:55 +0300 +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 + Thunderbird/78.13.0 +MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; - boundary="UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy" + boundary="6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN" This is an OpenPGP/MIME signed message (RFC 4880 and 3156) ---UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy -Content-Type: multipart/mixed; boundary="2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen"; +--6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN +Content-Type: multipart/mixed; boundary="qXbOytosKNHexW94IXHOXTCDf4kehiW4O"; protected-headers="v1" -From: Perpetuum Moobilee +From: Flowcrypt Compatibility To: flowcrypt.compatibility@gmail.com -Message-ID: -Subject: plaintext with detached signature - ---2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen -Content-Type: multipart/mixed; - boundary="------------318DB2E1763BE977A4E99886" -Content-Language: en-US +Message-ID: +Subject: mime email plain signed detached -This is a multi-part message in MIME format. ---------------318DB2E1763BE977A4E99886 +--qXbOytosKNHexW94IXHOXTCDf4kehiW4O Content-Type: text/plain; charset=utf-8; format=flowed -Content-Transfer-Encoding: quoted-printable - -some text +Content-Transfer-Encoding: base64 +Content-Language: en-US +c29tZQrmsYkKdHh0Cgo= ---2SVjN9BW1ncH06ndPSuxQAA7eogrqtJen-- +--qXbOytosKNHexW94IXHOXTCDf4kehiW4O-- ---UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy +--6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="OpenPGP_signature" -----BEGIN PGP SIGNATURE----- -Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption -Comment: Seamlessly send and receive encrypted email - -wsBcBAEBCAAGBQJhZddKAAoJEDow9MwKmo8QN04H/AgF1juV59IGlifqcw1b -pIbL7Wy2RGN3HRf71EKIQxq7Aw915MUS5KwJ71ip/BqBJs9UF7PvYJ3czwiv -Wp1Q/cihblMfpJaZyp1AC0shu6WAPZv6VE7Pk0eJ9AduYsQEifGQZPBQWnnN -E0mi1gUk/nTeXbAgf475sKjkZrWa02H8IC5LBKbew0smhjA/2BpkPJDFaWRS -WrQZr3kq4/ErIBCtFnnWx2k5ONNbsBi8mhWhI3Mr+us6JCYfrUiffpR39pBS -1OPOx4IAu1pJiZE7QWNJq77ldO0Sbdgq4J97wGmnSbb/0zTUwF6moGxgDJur -JqSoBWuMilggHft/Taq2HN8= -=ARBb + +wsF5BAABCAAjFiEE6PBRe6bX2rYIHJbkrawnnJUJMgcFAmFl4UMFAwAAAAAACgkQrawnnJUJMgc5 +wg/8DGXAdov+xgcdIZ9T4UVs02jdTTCaortoJP1pLs7hZMC17C7Qp51qC1K1IJdbs9L7YAg6N6HP +MzA0tWwPdIu952JbRPA9VsrBFfYyxGkEeOXkbB+4zTOe+QuJxDFl5yObnmCOf1PeuFhX+vr+0gL6 +bKgQd9MpPo766aTdwcVmKS8zkdmZWzsWcD22Lluaf2EV9qLTL95vqZb1h7B4vc69Bkgl8zzDNwmU +zr4yl3Bp29L6kz2PKpgK8wvwl5X2DlHotITbVCnyeqQanP5dOKvXkjcKZql+qxa1CEC6tIiH1jlz +cWqf78ekb8d7CJ6geSTEOYgub/J4bGaF6j5TpWtGczs+zAkcvquwkbSpmjjHvighqpgZETItpHil +FXED1wARj1t3yyzC7ZMVpUNYVtnw7+WdLk8JjTHyiR3IavMoLpvWQr9dYWwsPWqVSc9/CqAbxYgF +hrSTNES43hjo99ibKm3IzaxikMcxflaYVXaRoyRteV5/ZPJhsT8KBF3SH+nJoFsawNow5Akotdd1 +AqSnkjQEVICu0MMhpuT4GqbbB9EMQRMC//M2lCxsR6N6mCsIjX9qNbMzfC2fgcaqcRkCDiIm6s5t +kJlBhMVM9HII66mrd55yv310PzGv+sZvn/l/F5zyeTHTXWL2/ss2O62oe6E5NtWwc8B7BZulWD/L +9cU= +=BonZ -----END PGP SIGNATURE----- ---UxnIDWfEzsSNwl3ATmOiPdVTZfBXOLRjy-- +--6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN-- diff --git a/Core/source/test.ts b/Core/source/test.ts index 774236e95..8f5c9a336 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -648,7 +648,7 @@ ava.default('verify plain-text signed message that you edited after signing. Thi ava.default.only('verify signed message with detached signature by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached2')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed detached'); console.log(decryptData.toString()); From 82c59726e9ab8178ca0b730d33c8577828c80b66 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 22:29:32 +0300 Subject: [PATCH 63/79] wip --- .../mime-email-plain-signed-detached2.txt | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index e52299316..d8d36ee7a 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -40,19 +40,17 @@ Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="OpenPGP_signature" -----BEGIN PGP SIGNATURE----- - -wsF5BAABCAAjFiEE6PBRe6bX2rYIHJbkrawnnJUJMgcFAmFl4UMFAwAAAAAACgkQrawnnJUJMgc5 -wg/8DGXAdov+xgcdIZ9T4UVs02jdTTCaortoJP1pLs7hZMC17C7Qp51qC1K1IJdbs9L7YAg6N6HP -MzA0tWwPdIu952JbRPA9VsrBFfYyxGkEeOXkbB+4zTOe+QuJxDFl5yObnmCOf1PeuFhX+vr+0gL6 -bKgQd9MpPo766aTdwcVmKS8zkdmZWzsWcD22Lluaf2EV9qLTL95vqZb1h7B4vc69Bkgl8zzDNwmU -zr4yl3Bp29L6kz2PKpgK8wvwl5X2DlHotITbVCnyeqQanP5dOKvXkjcKZql+qxa1CEC6tIiH1jlz -cWqf78ekb8d7CJ6geSTEOYgub/J4bGaF6j5TpWtGczs+zAkcvquwkbSpmjjHvighqpgZETItpHil -FXED1wARj1t3yyzC7ZMVpUNYVtnw7+WdLk8JjTHyiR3IavMoLpvWQr9dYWwsPWqVSc9/CqAbxYgF -hrSTNES43hjo99ibKm3IzaxikMcxflaYVXaRoyRteV5/ZPJhsT8KBF3SH+nJoFsawNow5Akotdd1 -AqSnkjQEVICu0MMhpuT4GqbbB9EMQRMC//M2lCxsR6N6mCsIjX9qNbMzfC2fgcaqcRkCDiIm6s5t -kJlBhMVM9HII66mrd55yv310PzGv+sZvn/l/F5zyeTHTXWL2/ss2O62oe6E5NtWwc8B7BZulWD/L -9cU= -=BonZ +Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption +Comment: Seamlessly send and receive encrypted email + +wsBcBAEBCAAGBQJhZddKAAoJEDow9MwKmo8QN04H/AgF1juV59IGlifqcw1b +pIbL7Wy2RGN3HRf71EKIQxq7Aw915MUS5KwJ71ip/BqBJs9UF7PvYJ3czwiv +Wp1Q/cihblMfpJaZyp1AC0shu6WAPZv6VE7Pk0eJ9AduYsQEifGQZPBQWnnN +E0mi1gUk/nTeXbAgf475sKjkZrWa02H8IC5LBKbew0smhjA/2BpkPJDFaWRS +WrQZr3kq4/ErIBCtFnnWx2k5ONNbsBi8mhWhI3Mr+us6JCYfrUiffpR39pBS +1OPOx4IAu1pJiZE7QWNJq77ldO0Sbdgq4J97wGmnSbb/0zTUwF6moGxgDJur +JqSoBWuMilggHft/Taq2HN8= +=ARBb -----END PGP SIGNATURE----- --6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN-- From d0fa29988856239aa8d9d7db83061ec4ad7657ae Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 22:30:15 +0300 Subject: [PATCH 64/79] wip --- Core/source/gen-compat-assets.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 7aa6fabc3..939a01b84 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -226,7 +226,8 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - const data = "some text"; + // const data = "some text"; + const data = text.toString(); const signed = await PgpMsg.sign(signingPrv, data, true); await write(t, mimeEmail2(t, signed, data)); t.pass(); From a2f57b6b3afa707b33ee85c5c7496b6fa8b1e366 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 22:32:10 +0300 Subject: [PATCH 65/79] wip --- .../mime-email-plain-signed-detached.txt | 20 ++++++++++--------- .../mime-email-plain-signed-detached2.txt | 16 +++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached.txt b/Core/source/assets/compat/mime-email-plain-signed-detached.txt index 2f060245b..15d990b9b 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached.txt @@ -9,19 +9,21 @@ Subject: mime email plain signed detached To: flowcrypt.compatibility@gmail.com Content-Type: text/plain; charset="UTF-8" -some text +some +汉 +txt -----BEGIN PGP SIGNATURE----- Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wsBcBAEBCAAGBQJhZddKAAoJEDow9MwKmo8QN04H/AgF1juV59IGlifqcw1b -pIbL7Wy2RGN3HRf71EKIQxq7Aw915MUS5KwJ71ip/BqBJs9UF7PvYJ3czwiv -Wp1Q/cihblMfpJaZyp1AC0shu6WAPZv6VE7Pk0eJ9AduYsQEifGQZPBQWnnN -E0mi1gUk/nTeXbAgf475sKjkZrWa02H8IC5LBKbew0smhjA/2BpkPJDFaWRS -WrQZr3kq4/ErIBCtFnnWx2k5ONNbsBi8mhWhI3Mr+us6JCYfrUiffpR39pBS -1OPOx4IAu1pJiZE7QWNJq77ldO0Sbdgq4J97wGmnSbb/0zTUwF6moGxgDJur -JqSoBWuMilggHft/Taq2HN8= -=ARBb +wsBcBAEBCAAGBQJhZeJkAAoJEDow9MwKmo8QgbQH/0PB4Lqi5+a0VARUjw8M +1+IVlVQG6Js1zL8rZ5bIJm9aoG6D1UBYAptSvV0L0wSf5Kh6mOEl+6ENlFzq +eE5ouujaApr9tF68FEkhxDfRfNYN9NgEYxEYbR3fqpvqUPFyvrBIfy+KiT7l +aRuXDdZaSQgUWPxe9Vfmjy8J/UiH1JCV5T8/YkIM3oc43yeOiVfU7XcsPDoG +i0KkNZQ9oO/tnrFhgy7egVhFPborUN9h/g07Rk9tytHNZaCyXSofTM8Egk0m +ECP6/2adkl10/LjwBsfI7dMRetNUhKaYBwT8nA/+hsuQqRa1zxKswfMft5x8 +8hJ7APfAufmat4BwqpxTQgU= +=QShW -----END PGP SIGNATURE----- diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index d8d36ee7a..cea659af3 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -43,14 +43,14 @@ Content-Disposition: attachment; filename="OpenPGP_signature" Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wsBcBAEBCAAGBQJhZddKAAoJEDow9MwKmo8QN04H/AgF1juV59IGlifqcw1b -pIbL7Wy2RGN3HRf71EKIQxq7Aw915MUS5KwJ71ip/BqBJs9UF7PvYJ3czwiv -Wp1Q/cihblMfpJaZyp1AC0shu6WAPZv6VE7Pk0eJ9AduYsQEifGQZPBQWnnN -E0mi1gUk/nTeXbAgf475sKjkZrWa02H8IC5LBKbew0smhjA/2BpkPJDFaWRS -WrQZr3kq4/ErIBCtFnnWx2k5ONNbsBi8mhWhI3Mr+us6JCYfrUiffpR39pBS -1OPOx4IAu1pJiZE7QWNJq77ldO0Sbdgq4J97wGmnSbb/0zTUwF6moGxgDJur -JqSoBWuMilggHft/Taq2HN8= -=ARBb +wsBcBAEBCAAGBQJhZeJkAAoJEDow9MwKmo8QgbQH/0PB4Lqi5+a0VARUjw8M +1+IVlVQG6Js1zL8rZ5bIJm9aoG6D1UBYAptSvV0L0wSf5Kh6mOEl+6ENlFzq +eE5ouujaApr9tF68FEkhxDfRfNYN9NgEYxEYbR3fqpvqUPFyvrBIfy+KiT7l +aRuXDdZaSQgUWPxe9Vfmjy8J/UiH1JCV5T8/YkIM3oc43yeOiVfU7XcsPDoG +i0KkNZQ9oO/tnrFhgy7egVhFPborUN9h/g07Rk9tytHNZaCyXSofTM8Egk0m +ECP6/2adkl10/LjwBsfI7dMRetNUhKaYBwT8nA/+hsuQqRa1zxKswfMft5x8 +8hJ7APfAufmat4BwqpxTQgU= +=QShW -----END PGP SIGNATURE----- --6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN-- From 9e3c07da68e1f3a4341723c7738f12fbe4800ef9 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 22:44:45 +0300 Subject: [PATCH 66/79] wip --- Core/source/test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/source/test.ts b/Core/source/test.ts index 8f5c9a336..2f9330815 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -647,6 +647,11 @@ ava.default('verify plain-text signed message that you edited after signing. Thi }); ava.default.only('verify signed message with detached signature by providing it correct key', async t => { + const kk = getKeypairs('rsa1'); + console.log('----------------------'); + console.log(kk.keys[0].private); + console.log(kk.keys[0].passphrase); + console.log('----------------------'); const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached2')])); expect(decryptJson.replyType).equals('plain'); From 26373974a6491fdf5e6cecb118b9d6c67d223fac Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 22:58:59 +0300 Subject: [PATCH 67/79] wip --- .../mime-email-plain-signed-detached2.txt | 54 ++++++++++--------- Core/source/gen-compat-assets.ts | 3 +- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index cea659af3..dce4377a5 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -1,56 +1,60 @@ Return-Path: Received: from [192.168.88.243] ([176.100.5.125]) - by smtp.gmail.com with ESMTPSA id q7sm1107487lfc.159.2021.10.12.12.25.56 + by smtp.gmail.com with ESMTPSA id z6sm964274ljc.112.2021.10.12.12.57.41 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); - Tue, 12 Oct 2021 12:25:57 -0700 (PDT) + Tue, 12 Oct 2021 12:57:41 -0700 (PDT) To: flowcrypt.compatibility@gmail.com From: Flowcrypt Compatibility Subject: mime email plain signed detached -Message-ID: -Date: Tue, 12 Oct 2021 22:25:55 +0300 +Message-ID: <1bf47b68-85a3-f6af-460c-d323a774f363@gmail.com> +Date: Tue, 12 Oct 2021 22:57:40 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; - boundary="6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN" + boundary="hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ" This is an OpenPGP/MIME signed message (RFC 4880 and 3156) ---6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN -Content-Type: multipart/mixed; boundary="qXbOytosKNHexW94IXHOXTCDf4kehiW4O"; +--hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ +Content-Type: multipart/mixed; boundary="hoT9LflcSYM3GtoaeoAPEXZodu41YW4bQ"; protected-headers="v1" From: Flowcrypt Compatibility To: flowcrypt.compatibility@gmail.com -Message-ID: +Message-ID: <1bf47b68-85a3-f6af-460c-d323a774f363@gmail.com> Subject: mime email plain signed detached ---qXbOytosKNHexW94IXHOXTCDf4kehiW4O +--hoT9LflcSYM3GtoaeoAPEXZodu41YW4bQ Content-Type: text/plain; charset=utf-8; format=flowed -Content-Transfer-Encoding: base64 +Content-Transfer-Encoding: quoted-printable Content-Language: en-US -c29tZQrmsYkKdHh0Cgo= +some text ---qXbOytosKNHexW94IXHOXTCDf4kehiW4O-- ---6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN + +--hoT9LflcSYM3GtoaeoAPEXZodu41YW4bQ-- + +--hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="OpenPGP_signature" -----BEGIN PGP SIGNATURE----- -Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption -Comment: Seamlessly send and receive encrypted email - -wsBcBAEBCAAGBQJhZeJkAAoJEDow9MwKmo8QgbQH/0PB4Lqi5+a0VARUjw8M -1+IVlVQG6Js1zL8rZ5bIJm9aoG6D1UBYAptSvV0L0wSf5Kh6mOEl+6ENlFzq -eE5ouujaApr9tF68FEkhxDfRfNYN9NgEYxEYbR3fqpvqUPFyvrBIfy+KiT7l -aRuXDdZaSQgUWPxe9Vfmjy8J/UiH1JCV5T8/YkIM3oc43yeOiVfU7XcsPDoG -i0KkNZQ9oO/tnrFhgy7egVhFPborUN9h/g07Rk9tytHNZaCyXSofTM8Egk0m -ECP6/2adkl10/LjwBsfI7dMRetNUhKaYBwT8nA/+hsuQqRa1zxKswfMft5x8 -8hJ7APfAufmat4BwqpxTQgU= -=QShW + +wsF5BAABCAAjFiEEVSDKziy2HqcT5bAFf95oVUiup4gFAmFl6LQFAwAAAAAACgkQf95oVUiup4ig +KA//R8Hi1ZWVO66+wnXkAdqxrlCOTF6gzq3jZotUmLkFobiwdxltmW43LKjkFtI02WN16J9EhMXP +xBVg8AeAjZVUKeilD0elclecMIkh4D9qY93AhHa8YDlDYdkB/it14zR5g+W7jTaoUdxmdmkYxCTA +9+01RWIMGYGb1SkTY3dmh00Vw5jr9NtHoi8zornBT8tOGwjE+EKKkxMbLnMNFHeuiV4Yx6+b6bmy +1s01NsAvAZo9dZMrzBsqaMB+NK+qCE+n6EEnuHOZ2aNtvo20ZZpcFoe2llkRf0VjuBNjNkp8tkpe +IXvirvpX0dPEDu5viYgrTzBgD3IKojI9rZt1eot+pM1cgHLqpGHo7QJvyDDZ9B+VKzZcLYjxuIoa +E/8Vb+ov5RZV4dFJJHGHPGC3dTYiXkBGvvLysPvjZcZEVKPd917LTJHCf4v88DLiHUSvrdt/wOhx +MDIXnUwDa4X0kCeQoQuDooZlCuT4qCmp9giUwBh2jubP4NDgTQgqoTKkYnP7ee/hvHfdLre5GGbK +g266FX7AunoEMhKSBsYWAbFmr7PwqSED6urR0fKLI9PSQ5mqU5lb1bSpSd7QHsbYiJt7IO9V0OmW +MbjQDqG5FY8igJdkt3JMQXQyrOiRCj0ynuWowtSe7LOT+k0qs4OXOOirZodH9EvT/H2KzHICR8E1 +wUU= +=po6h -----END PGP SIGNATURE----- ---6UiWBWdXbZTmbBsEUMno1KZ2DrsqwwGHN-- +--hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ-- diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 939a01b84..7aa6fabc3 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -226,8 +226,7 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - // const data = "some text"; - const data = text.toString(); + const data = "some text"; const signed = await PgpMsg.sign(signingPrv, data, true); await write(t, mimeEmail2(t, signed, data)); t.pass(); From c1138984c1a33050dacf8ab6a6bcdf2cb367153a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 23:04:17 +0300 Subject: [PATCH 68/79] wip --- .../mime-email-plain-signed-detached.txt | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached.txt b/Core/source/assets/compat/mime-email-plain-signed-detached.txt index 15d990b9b..814e9effd 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached.txt @@ -9,21 +9,19 @@ Subject: mime email plain signed detached To: flowcrypt.compatibility@gmail.com Content-Type: text/plain; charset="UTF-8" -some -汉 -txt +some text -----BEGIN PGP SIGNATURE----- Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wsBcBAEBCAAGBQJhZeJkAAoJEDow9MwKmo8QgbQH/0PB4Lqi5+a0VARUjw8M -1+IVlVQG6Js1zL8rZ5bIJm9aoG6D1UBYAptSvV0L0wSf5Kh6mOEl+6ENlFzq -eE5ouujaApr9tF68FEkhxDfRfNYN9NgEYxEYbR3fqpvqUPFyvrBIfy+KiT7l -aRuXDdZaSQgUWPxe9Vfmjy8J/UiH1JCV5T8/YkIM3oc43yeOiVfU7XcsPDoG -i0KkNZQ9oO/tnrFhgy7egVhFPborUN9h/g07Rk9tytHNZaCyXSofTM8Egk0m -ECP6/2adkl10/LjwBsfI7dMRetNUhKaYBwT8nA/+hsuQqRa1zxKswfMft5x8 -8hJ7APfAufmat4BwqpxTQgU= -=QShW +wsBcBAEBCAAGBQJhZeosAAoJEDow9MwKmo8Qev4H/02N6ue1kpZ+VSdPzu4o +bgvtHEwk6wJEXN1eSh//bSY8owmk+DOHiF7YNI3CwJTZCtLEKh7Tt8RY7oB7 +0oNzVw7LEZd6JwdUZfaU1rnV5zZvo01SuJs/5IS21LU5riQntri6o/9Vn0hI +rbHlYqVdm12bBP0o1XilISHo8zm3Sy6ANb2JLVWqoRf9MThsj/H8K82zkJuK +2fGaZEQqcJ/CfDckhsMrU4V6Ymw15cMR4MVMXcZ/xoMJdnrBlNZ/nVGN9KaT +np03NLc0ofo6uIdt5J7c9uXQuvW1YuHFKyZJHZgo/Z92GV+hE/myV1PSHs06 +tL8L5XR3+yYrMHVSfh2jZjo= +=0985 -----END PGP SIGNATURE----- From e3078e350d13653162e2246db494052ef093fdda Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 23:05:28 +0300 Subject: [PATCH 69/79] wip --- .../mime-email-plain-signed-detached2.txt | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index dce4377a5..e2789986a 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -42,19 +42,17 @@ Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="OpenPGP_signature" -----BEGIN PGP SIGNATURE----- - -wsF5BAABCAAjFiEEVSDKziy2HqcT5bAFf95oVUiup4gFAmFl6LQFAwAAAAAACgkQf95oVUiup4ig -KA//R8Hi1ZWVO66+wnXkAdqxrlCOTF6gzq3jZotUmLkFobiwdxltmW43LKjkFtI02WN16J9EhMXP -xBVg8AeAjZVUKeilD0elclecMIkh4D9qY93AhHa8YDlDYdkB/it14zR5g+W7jTaoUdxmdmkYxCTA -9+01RWIMGYGb1SkTY3dmh00Vw5jr9NtHoi8zornBT8tOGwjE+EKKkxMbLnMNFHeuiV4Yx6+b6bmy -1s01NsAvAZo9dZMrzBsqaMB+NK+qCE+n6EEnuHOZ2aNtvo20ZZpcFoe2llkRf0VjuBNjNkp8tkpe -IXvirvpX0dPEDu5viYgrTzBgD3IKojI9rZt1eot+pM1cgHLqpGHo7QJvyDDZ9B+VKzZcLYjxuIoa -E/8Vb+ov5RZV4dFJJHGHPGC3dTYiXkBGvvLysPvjZcZEVKPd917LTJHCf4v88DLiHUSvrdt/wOhx -MDIXnUwDa4X0kCeQoQuDooZlCuT4qCmp9giUwBh2jubP4NDgTQgqoTKkYnP7ee/hvHfdLre5GGbK -g266FX7AunoEMhKSBsYWAbFmr7PwqSED6urR0fKLI9PSQ5mqU5lb1bSpSd7QHsbYiJt7IO9V0OmW -MbjQDqG5FY8igJdkt3JMQXQyrOiRCj0ynuWowtSe7LOT+k0qs4OXOOirZodH9EvT/H2KzHICR8E1 -wUU= -=po6h +Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption +Comment: Seamlessly send and receive encrypted email + +wsBcBAEBCAAGBQJhZeosAAoJEDow9MwKmo8Qev4H/02N6ue1kpZ+VSdPzu4o +bgvtHEwk6wJEXN1eSh//bSY8owmk+DOHiF7YNI3CwJTZCtLEKh7Tt8RY7oB7 +0oNzVw7LEZd6JwdUZfaU1rnV5zZvo01SuJs/5IS21LU5riQntri6o/9Vn0hI +rbHlYqVdm12bBP0o1XilISHo8zm3Sy6ANb2JLVWqoRf9MThsj/H8K82zkJuK +2fGaZEQqcJ/CfDckhsMrU4V6Ymw15cMR4MVMXcZ/xoMJdnrBlNZ/nVGN9KaT +np03NLc0ofo6uIdt5J7c9uXQuvW1YuHFKyZJHZgo/Z92GV+hE/myV1PSHs06 +tL8L5XR3+yYrMHVSfh2jZjo= +=0985 -----END PGP SIGNATURE----- --hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ-- From 9f10bd85c365333d91a75e6ab326d1cff8f90088 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 23:06:04 +0300 Subject: [PATCH 70/79] wip --- Core/source/test.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 2f9330815..8f5c9a336 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -647,11 +647,6 @@ ava.default('verify plain-text signed message that you edited after signing. Thi }); ava.default.only('verify signed message with detached signature by providing it correct key', async t => { - const kk = getKeypairs('rsa1'); - console.log('----------------------'); - console.log(kk.keys[0].private); - console.log(kk.keys[0].passphrase); - console.log('----------------------'); const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached2')])); expect(decryptJson.replyType).equals('plain'); From e7b157c3e9626533f43784504935b97888336ce5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 23:07:41 +0300 Subject: [PATCH 71/79] wip --- Core/source/gen-compat-assets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 7aa6fabc3..6b24a04aa 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -226,7 +226,7 @@ ava.default('mime-email-plain-signed-detached.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - const data = "some text"; + const data = "some text\n"; const signed = await PgpMsg.sign(signingPrv, data, true); await write(t, mimeEmail2(t, signed, data)); t.pass(); From 20d847027928ee7656dba5cfa4c884feb91e8645 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 23:09:33 +0300 Subject: [PATCH 72/79] wip --- .../compat/mime-email-plain-signed-detached.txt | 17 +++++++++-------- .../mime-email-plain-signed-detached2.txt | 16 ++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached.txt b/Core/source/assets/compat/mime-email-plain-signed-detached.txt index 814e9effd..1de34ae50 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached.txt @@ -11,17 +11,18 @@ Content-Type: text/plain; charset="UTF-8" some text + -----BEGIN PGP SIGNATURE----- Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wsBcBAEBCAAGBQJhZeosAAoJEDow9MwKmo8Qev4H/02N6ue1kpZ+VSdPzu4o -bgvtHEwk6wJEXN1eSh//bSY8owmk+DOHiF7YNI3CwJTZCtLEKh7Tt8RY7oB7 -0oNzVw7LEZd6JwdUZfaU1rnV5zZvo01SuJs/5IS21LU5riQntri6o/9Vn0hI -rbHlYqVdm12bBP0o1XilISHo8zm3Sy6ANb2JLVWqoRf9MThsj/H8K82zkJuK -2fGaZEQqcJ/CfDckhsMrU4V6Ymw15cMR4MVMXcZ/xoMJdnrBlNZ/nVGN9KaT -np03NLc0ofo6uIdt5J7c9uXQuvW1YuHFKyZJHZgo/Z92GV+hE/myV1PSHs06 -tL8L5XR3+yYrMHVSfh2jZjo= -=0985 +wsBcBAEBCAAGBQJhZes5AAoJEDow9MwKmo8QBQYH/jzSstB9q65KQysOn5yK +Hjp1pIcqVnXql9qZ2ALz8qVZ+iR8GuqxA+iXFZqx6k+owUa5AbVRSZ14wN65 +gI67J/N72XTs9xDHhAxaq65rEIMnUxvjyaO/83srCT2n/EEY6Cp7IW91/ml1 +Q/BDltqb55tu7iFP5aERvlY/seDkAMc5X37S+RAvgnnZeLR/Dzy9ArLPSEiR +UL6l5y/kqgWSz+98fLP/GA2X48JCmXQjtcFQ7iuL/amf0CR62tsHeD0fvP01 +ComQm/I1MBIdrLxjeVp3M87qwKNxuoluGFgbVVaKLPy+kwx0jcLtfYisA3Qy +J0j5S2giARCEzb6lUrYCW40= +=rOGQ -----END PGP SIGNATURE----- diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index e2789986a..a55b547c6 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -45,14 +45,14 @@ Content-Disposition: attachment; filename="OpenPGP_signature" Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption Comment: Seamlessly send and receive encrypted email -wsBcBAEBCAAGBQJhZeosAAoJEDow9MwKmo8Qev4H/02N6ue1kpZ+VSdPzu4o -bgvtHEwk6wJEXN1eSh//bSY8owmk+DOHiF7YNI3CwJTZCtLEKh7Tt8RY7oB7 -0oNzVw7LEZd6JwdUZfaU1rnV5zZvo01SuJs/5IS21LU5riQntri6o/9Vn0hI -rbHlYqVdm12bBP0o1XilISHo8zm3Sy6ANb2JLVWqoRf9MThsj/H8K82zkJuK -2fGaZEQqcJ/CfDckhsMrU4V6Ymw15cMR4MVMXcZ/xoMJdnrBlNZ/nVGN9KaT -np03NLc0ofo6uIdt5J7c9uXQuvW1YuHFKyZJHZgo/Z92GV+hE/myV1PSHs06 -tL8L5XR3+yYrMHVSfh2jZjo= -=0985 +wsBcBAEBCAAGBQJhZes5AAoJEDow9MwKmo8QBQYH/jzSstB9q65KQysOn5yK +Hjp1pIcqVnXql9qZ2ALz8qVZ+iR8GuqxA+iXFZqx6k+owUa5AbVRSZ14wN65 +gI67J/N72XTs9xDHhAxaq65rEIMnUxvjyaO/83srCT2n/EEY6Cp7IW91/ml1 +Q/BDltqb55tu7iFP5aERvlY/seDkAMc5X37S+RAvgnnZeLR/Dzy9ArLPSEiR +UL6l5y/kqgWSz+98fLP/GA2X48JCmXQjtcFQ7iuL/amf0CR62tsHeD0fvP01 +ComQm/I1MBIdrLxjeVp3M87qwKNxuoluGFgbVVaKLPy+kwx0jcLtfYisA3Qy +J0j5S2giARCEzb6lUrYCW40= +=rOGQ -----END PGP SIGNATURE----- --hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ-- From a36f6446f850ed2261c99d8285d38a05f0d064d9 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 23:16:50 +0300 Subject: [PATCH 73/79] wip --- Core/source/test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/source/test.ts b/Core/source/test.ts index 8f5c9a336..a4cebbe71 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -646,6 +646,9 @@ ava.default('verify plain-text signed message that you edited after signing. Thi t.pass(); }); +// Can't get it working right. Thunderbird doesn't allow exporting MIME message when composing +// and attempt to replace signature in the sent message by signature generated with key used here +// just didn't work. So meanwhile giving up on it. ava.default.only('verify signed message with detached signature by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached2')])); From b91faed6aaefeb1663ec37bb4939f01c6908e7c5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 12 Oct 2021 23:19:04 +0300 Subject: [PATCH 74/79] skip deteched signature test --- Core/source/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index a4cebbe71..c1b793b73 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -649,7 +649,7 @@ ava.default('verify plain-text signed message that you edited after signing. Thi // Can't get it working right. Thunderbird doesn't allow exporting MIME message when composing // and attempt to replace signature in the sent message by signature generated with key used here // just didn't work. So meanwhile giving up on it. -ava.default.only('verify signed message with detached signature by providing it correct key', async t => { +ava.default.skip('verify signed message with detached signature by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached2')])); expect(decryptJson.replyType).equals('plain'); From dc9725123fae3c2c07ed9755672a241e80deab8a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 13 Oct 2021 02:12:43 +0300 Subject: [PATCH 75/79] wip --- .../mime-email-plain-signed-detached2.txt | 65 +++++++++---------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt index a55b547c6..e856127d0 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt @@ -1,58 +1,53 @@ -Return-Path: -Received: from [192.168.88.243] ([176.100.5.125]) - by smtp.gmail.com with ESMTPSA id z6sm964274ljc.112.2021.10.12.12.57.41 - for - (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); - Tue, 12 Oct 2021 12:57:41 -0700 (PDT) -To: flowcrypt.compatibility@gmail.com -From: Flowcrypt Compatibility +Return-Path: +X-Original-To: t@est.com +Delivered-To: t@est.com +Received: from [192.168.56.1] (unknown [192.168.56.1]) + by est.com (Postfix) with ESMTPS id E08F2103ED0 + for ; Tue, 12 Oct 2021 23:06:02 +0000 (UTC) +To: t@est.com +From: Test User Subject: mime email plain signed detached -Message-ID: <1bf47b68-85a3-f6af-460c-d323a774f363@gmail.com> -Date: Tue, 12 Oct 2021 22:57:40 +0300 +Message-ID: <920dc165-7ba2-3f36-3177-a8e76bae4ddd@est.com> +Date: Wed, 13 Oct 2021 02:06:02 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; - boundary="hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ" + boundary="1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG" This is an OpenPGP/MIME signed message (RFC 4880 and 3156) ---hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ -Content-Type: multipart/mixed; boundary="hoT9LflcSYM3GtoaeoAPEXZodu41YW4bQ"; +--1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG +Content-Type: multipart/mixed; boundary="zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw"; protected-headers="v1" -From: Flowcrypt Compatibility -To: flowcrypt.compatibility@gmail.com -Message-ID: <1bf47b68-85a3-f6af-460c-d323a774f363@gmail.com> +From: Test User +To: t@est.com +Message-ID: <920dc165-7ba2-3f36-3177-a8e76bae4ddd@est.com> Subject: mime email plain signed detached ---hoT9LflcSYM3GtoaeoAPEXZodu41YW4bQ +--zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw Content-Type: text/plain; charset=utf-8; format=flowed -Content-Transfer-Encoding: quoted-printable +Content-Transfer-Encoding: base64 Content-Language: en-US -some text +c29tZQrmsYkKdHh0Cgo= +--zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw-- - ---hoT9LflcSYM3GtoaeoAPEXZodu41YW4bQ-- - ---hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ +--1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="OpenPGP_signature" -----BEGIN PGP SIGNATURE----- -Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption -Comment: Seamlessly send and receive encrypted email - -wsBcBAEBCAAGBQJhZes5AAoJEDow9MwKmo8QBQYH/jzSstB9q65KQysOn5yK -Hjp1pIcqVnXql9qZ2ALz8qVZ+iR8GuqxA+iXFZqx6k+owUa5AbVRSZ14wN65 -gI67J/N72XTs9xDHhAxaq65rEIMnUxvjyaO/83srCT2n/EEY6Cp7IW91/ml1 -Q/BDltqb55tu7iFP5aERvlY/seDkAMc5X37S+RAvgnnZeLR/Dzy9ArLPSEiR -UL6l5y/kqgWSz+98fLP/GA2X48JCmXQjtcFQ7iuL/amf0CR62tsHeD0fvP01 -ComQm/I1MBIdrLxjeVp3M87qwKNxuoluGFgbVVaKLPy+kwx0jcLtfYisA3Qy -J0j5S2giARCEzb6lUrYCW40= -=rOGQ + +wsB5BAABCAAjFiEE52hT4Sig03bK5HwUOjD0zAqajxAFAmFmFNoFAwAAAAAACgkQOjD0zAqajxBM +dgf7BDgUTDQ4AvhUdyJ8xMtWpzRKCWz1tp2ErqciQCamXJxOkoBMlcY8mrohYgbNtOvabKguknWT +NUpzgcnU1DbtL/wB43tJNfAmquLhl3dw5TBPieg7lImZSNAyS5H0Uxtuxze0nVrdgCgVoyaPuC/7 +PBoMMUM1LLrnP5LJM9d10Hku6BqsgYgI2GDx7MFiWkUIHWFcSLaZk+Ttc7Dpau40bpuJDxW5Cd1p +OrBkuuuSSlYVQkZB8ABZ2T/OT+H06kGuvN5SV9UDTuSHi+Uk355bzWJau5hEQHXoT+O4TskJlJAG ++VkotOZYUtGyPWdwKsun1/w8w2xc9GCMjnb2owFXdQ== +=bMPl -----END PGP SIGNATURE----- ---hTjLPt39apiyzP4ygKIkZaDYyHWQcexiZ-- +--1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG-- From a7e49ee7e4c8abd7f938d99adb739ebe1fab1023 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 13 Oct 2021 02:15:24 +0300 Subject: [PATCH 76/79] fixed detached test --- .../mime-email-plain-signed-detached.txt | 77 ++++++++++++------- .../mime-email-plain-signed-detached2.txt | 53 ------------- Core/source/gen-compat-assets.ts | 10 --- Core/source/test.ts | 7 +- 4 files changed, 53 insertions(+), 94 deletions(-) delete mode 100644 Core/source/assets/compat/mime-email-plain-signed-detached2.txt diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached.txt b/Core/source/assets/compat/mime-email-plain-signed-detached.txt index 1de34ae50..e856127d0 100644 --- a/Core/source/assets/compat/mime-email-plain-signed-detached.txt +++ b/Core/source/assets/compat/mime-email-plain-signed-detached.txt @@ -1,28 +1,53 @@ -Delivered-To: flowcrypt.compatibility@gmail.com -Return-Path: -Openpgp: id=E76853E128A0D376CAE47C143A30F4CC0A9A8F10 -From: flowcrypt.compatibility@gmail.com -MIME-Version: 1.0 -Date: Thu, 2 Nov 2017 17:54:14 -0700 -Message-ID: -Subject: mime email plain signed detached -To: flowcrypt.compatibility@gmail.com -Content-Type: text/plain; charset="UTF-8" - -some text - - +Return-Path: +X-Original-To: t@est.com +Delivered-To: t@est.com +Received: from [192.168.56.1] (unknown [192.168.56.1]) + by est.com (Postfix) with ESMTPS id E08F2103ED0 + for ; Tue, 12 Oct 2021 23:06:02 +0000 (UTC) +To: t@est.com +From: Test User +Subject: mime email plain signed detached +Message-ID: <920dc165-7ba2-3f36-3177-a8e76bae4ddd@est.com> +Date: Wed, 13 Oct 2021 02:06:02 +0300 +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 + Thunderbird/78.13.0 +MIME-Version: 1.0 +Content-Type: multipart/signed; micalg=pgp-sha256; + protocol="application/pgp-signature"; + boundary="1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG" + +This is an OpenPGP/MIME signed message (RFC 4880 and 3156) +--1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG +Content-Type: multipart/mixed; boundary="zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw"; + protected-headers="v1" +From: Test User +To: t@est.com +Message-ID: <920dc165-7ba2-3f36-3177-a8e76bae4ddd@est.com> +Subject: mime email plain signed detached + +--zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw +Content-Type: text/plain; charset=utf-8; format=flowed +Content-Transfer-Encoding: base64 +Content-Language: en-US + +c29tZQrmsYkKdHh0Cgo= + +--zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw-- + +--1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG +Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" +Content-Description: OpenPGP digital signature +Content-Disposition: attachment; filename="OpenPGP_signature" + -----BEGIN PGP SIGNATURE----- -Version: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption -Comment: Seamlessly send and receive encrypted email - -wsBcBAEBCAAGBQJhZes5AAoJEDow9MwKmo8QBQYH/jzSstB9q65KQysOn5yK -Hjp1pIcqVnXql9qZ2ALz8qVZ+iR8GuqxA+iXFZqx6k+owUa5AbVRSZ14wN65 -gI67J/N72XTs9xDHhAxaq65rEIMnUxvjyaO/83srCT2n/EEY6Cp7IW91/ml1 -Q/BDltqb55tu7iFP5aERvlY/seDkAMc5X37S+RAvgnnZeLR/Dzy9ArLPSEiR -UL6l5y/kqgWSz+98fLP/GA2X48JCmXQjtcFQ7iuL/amf0CR62tsHeD0fvP01 -ComQm/I1MBIdrLxjeVp3M87qwKNxuoluGFgbVVaKLPy+kwx0jcLtfYisA3Qy -J0j5S2giARCEzb6lUrYCW40= -=rOGQ + +wsB5BAABCAAjFiEE52hT4Sig03bK5HwUOjD0zAqajxAFAmFmFNoFAwAAAAAACgkQOjD0zAqajxBM +dgf7BDgUTDQ4AvhUdyJ8xMtWpzRKCWz1tp2ErqciQCamXJxOkoBMlcY8mrohYgbNtOvabKguknWT +NUpzgcnU1DbtL/wB43tJNfAmquLhl3dw5TBPieg7lImZSNAyS5H0Uxtuxze0nVrdgCgVoyaPuC/7 +PBoMMUM1LLrnP5LJM9d10Hku6BqsgYgI2GDx7MFiWkUIHWFcSLaZk+Ttc7Dpau40bpuJDxW5Cd1p +OrBkuuuSSlYVQkZB8ABZ2T/OT+H06kGuvN5SV9UDTuSHi+Uk355bzWJau5hEQHXoT+O4TskJlJAG ++VkotOZYUtGyPWdwKsun1/w8w2xc9GCMjnb2owFXdQ== +=bMPl -----END PGP SIGNATURE----- - + +--1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG-- diff --git a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt b/Core/source/assets/compat/mime-email-plain-signed-detached2.txt deleted file mode 100644 index e856127d0..000000000 --- a/Core/source/assets/compat/mime-email-plain-signed-detached2.txt +++ /dev/null @@ -1,53 +0,0 @@ -Return-Path: -X-Original-To: t@est.com -Delivered-To: t@est.com -Received: from [192.168.56.1] (unknown [192.168.56.1]) - by est.com (Postfix) with ESMTPS id E08F2103ED0 - for ; Tue, 12 Oct 2021 23:06:02 +0000 (UTC) -To: t@est.com -From: Test User -Subject: mime email plain signed detached -Message-ID: <920dc165-7ba2-3f36-3177-a8e76bae4ddd@est.com> -Date: Wed, 13 Oct 2021 02:06:02 +0300 -User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 - Thunderbird/78.13.0 -MIME-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-sha256; - protocol="application/pgp-signature"; - boundary="1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG" - -This is an OpenPGP/MIME signed message (RFC 4880 and 3156) ---1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG -Content-Type: multipart/mixed; boundary="zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw"; - protected-headers="v1" -From: Test User -To: t@est.com -Message-ID: <920dc165-7ba2-3f36-3177-a8e76bae4ddd@est.com> -Subject: mime email plain signed detached - ---zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw -Content-Type: text/plain; charset=utf-8; format=flowed -Content-Transfer-Encoding: base64 -Content-Language: en-US - -c29tZQrmsYkKdHh0Cgo= - ---zB40xvQ1bEP0WaDoW1b6PiXYa0sf6aLHw-- - ---1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG -Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" -Content-Description: OpenPGP digital signature -Content-Disposition: attachment; filename="OpenPGP_signature" - ------BEGIN PGP SIGNATURE----- - -wsB5BAABCAAjFiEE52hT4Sig03bK5HwUOjD0zAqajxAFAmFmFNoFAwAAAAAACgkQOjD0zAqajxBM -dgf7BDgUTDQ4AvhUdyJ8xMtWpzRKCWz1tp2ErqciQCamXJxOkoBMlcY8mrohYgbNtOvabKguknWT -NUpzgcnU1DbtL/wB43tJNfAmquLhl3dw5TBPieg7lImZSNAyS5H0Uxtuxze0nVrdgCgVoyaPuC/7 -PBoMMUM1LLrnP5LJM9d10Hku6BqsgYgI2GDx7MFiWkUIHWFcSLaZk+Ttc7Dpau40bpuJDxW5Cd1p -OrBkuuuSSlYVQkZB8ABZ2T/OT+H06kGuvN5SV9UDTuSHi+Uk355bzWJau5hEQHXoT+O4TskJlJAG -+VkotOZYUtGyPWdwKsun1/w8w2xc9GCMjnb2owFXdQ== -=bMPl ------END PGP SIGNATURE----- - ---1C2MFssN1e2UeK7Q7Fok4Ko9VNn7xQryG-- diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 6b24a04aa..4f5dba5e8 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -221,13 +221,3 @@ ava.default('mime-email-plain-signed.txt', async t => { await write(t, mimeEmail2(t, signed)); t.pass(); }); - -ava.default('mime-email-plain-signed-detached.txt', async t => { - const { keys } = getKeypairs('rsa1'); - const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; - if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - const data = "some text\n"; - const signed = await PgpMsg.sign(signingPrv, data, true); - await write(t, mimeEmail2(t, signed, data)); - t.pass(); -}); diff --git a/Core/source/test.ts b/Core/source/test.ts index c1b793b73..774236e95 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -646,12 +646,9 @@ ava.default('verify plain-text signed message that you edited after signing. Thi t.pass(); }); -// Can't get it working right. Thunderbird doesn't allow exporting MIME message when composing -// and attempt to replace signature in the sent message by signature generated with key used here -// just didn't work. So meanwhile giving up on it. -ava.default.skip('verify signed message with detached signature by providing it correct key', async t => { +ava.default.only('verify signed message with detached signature by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached2')])); + const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed detached'); console.log(decryptData.toString()); From 488667c2bf2b027560fb6a0323f570bf30e96b1d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 13 Oct 2021 02:16:09 +0300 Subject: [PATCH 77/79] enable all tests --- Core/source/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 774236e95..1836a54ac 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -646,7 +646,7 @@ ava.default('verify plain-text signed message that you edited after signing. Thi t.pass(); }); -ava.default.only('verify signed message with detached signature by providing it correct key', async t => { +ava.default('verify signed message with detached signature by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); expect(decryptJson.replyType).equals('plain'); From 0760e04aabe3a5802665beeb39070f1c165f310a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 13 Oct 2021 19:20:04 +0300 Subject: [PATCH 78/79] corrections after code review --- Core/source/core/pgp-msg.ts | 8 +++++- Core/source/mobile-interface/endpoints.ts | 1 - Core/source/mobile-interface/format-output.ts | 27 ++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 80d20c10c..abf0ee86d 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -52,7 +52,13 @@ type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: Open type OpenpgpMsgOrCleartext = OpenPGP.message.Message | OpenPGP.cleartext.CleartextMessage; -export type VerifyRes = { signer?: string; match: boolean | null; error?: string; }; +export type VerifyRes = { + signer?: string; + match: boolean | null; + error?: string; + mixed?: boolean; + partial?: boolean; +}; export type PgpMsgTypeResult = { armored: boolean, type: MsgBlockType } | undefined; export type DecryptResult = DecryptSuccess | DecryptError; export type DiagnoseMsgPubkeysResult = { found_match: boolean, receivers: number, }; diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 6ab637d37..e911307b1 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -90,7 +90,6 @@ export class Endpoints { } else { rawBlocks.push(MsgBlock.fromContent('encryptedMsg', new Buf(Buf.concat(data)))); } - for (const rawBlock of rawBlocks) console.log(JSON.stringify(rawBlock) + '\n'); const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { diff --git a/Core/source/mobile-interface/format-output.ts b/Core/source/mobile-interface/format-output.ts index 4d04cc2d7..b687abfc7 100644 --- a/Core/source/mobile-interface/format-output.ts +++ b/Core/source/mobile-interface/format-output.ts @@ -72,9 +72,23 @@ export const fmtContentBlock = (allContentBlocks: MsgBlock[]): { contentBlock: M imgsAtTheBottom.push(plainImgBlock); } } + var verifyRes: (VerifyRes | undefined) = undefined; + var mixedSignatures = false; + var signedBlockCount = 0; for (const block of contentBlocks) { - if (!verifyRes && block.verifyRes) verifyRes = block.verifyRes; + if (block.verifyRes) { + ++signedBlockCount; + if (!verifyRes) { + verifyRes = block.verifyRes; + } else if (!block.verifyRes.match) { + if (verifyRes.match) { + verifyRes = block.verifyRes; + } + } else if (verifyRes.match && block.verifyRes.signer !== verifyRes.signer) { + mixedSignatures = true; + } + } if (block.type === 'decryptedText') { msgContentAsHtml += fmtMsgContentBlockAsHtml(Str.asEscapedHtml(block.content.toString()), 'green'); msgContentAsText += block.content.toString() + '\n'; @@ -97,6 +111,16 @@ export const fmtContentBlock = (allContentBlocks: MsgBlock[]): { contentBlock: M msgContentAsText += block.content.toString() + '\n'; } } + + if (verifyRes && verifyRes.match) { + if (mixedSignatures) { + verifyRes.mixed = true; + } + if (signedBlockCount > 0 && signedBlockCount != contentBlocks.length) { + verifyRes.partial = true; + } + } + for (const inlineImg of imgsAtTheBottom.concat(Object.values(inlineImgsByCid))) { // render any images we did not insert into content, at the bottom let alt = `${inlineImg.attMeta!.name || '(unnamed image)'} - ${inlineImg.attMeta!.length! / 1024}kb`; // in current usage, as used by `endpoints.ts`: `block.attMeta!.data` actually contains base64 encoded data, not Uint8Array as the type claims @@ -104,6 +128,7 @@ export const fmtContentBlock = (allContentBlocks: MsgBlock[]): { contentBlock: M msgContentAsHtml += fmtMsgContentBlockAsHtml(inlineImgTag, 'plain'); msgContentAsText += `[image: ${alt}]\n`; } + msgContentAsHtml = ` From 28e75c43a1c3e766215db89c286c404a183cf54a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 13 Oct 2021 19:21:51 +0300 Subject: [PATCH 79/79] remove unnecessary log --- Core/source/test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 1836a54ac..e5633249a 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -651,7 +651,6 @@ ava.default('verify signed message with detached signature by providing it corre const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed detached'); - console.log(decryptData.toString()); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); expect(parsedDecryptData.verifyRes.match).equals(true);