Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to OpenPGP v5 #4725

Merged
merged 105 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
a1bdf38
wip
Sep 29, 2022
e657314
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Oct 1, 2022
7884761
re-wire streams
Oct 6, 2022
872e73b
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Oct 6, 2022
b41a0a4
Added tsconfig.streams.json
Oct 6, 2022
256820b
prepare resolve-module for test (wip)
Oct 6, 2022
e1896a1
replace paths in test
rrrooommmaaa Oct 6, 2022
7901816
fixes
rrrooommmaaa Oct 7, 2022
997582d
allowJs in tsc-compiler
rrrooommmaaa Oct 7, 2022
c096acf
wire streams to extension
rrrooommmaaa Oct 8, 2022
dae17fc
requireStreams
Oct 8, 2022
0d38c39
regex fix
Oct 8, 2022
ff2a334
lint fix
Oct 8, 2022
164e3c7
mimick old behaviour: extract signerLongids when no pubkeys are supp…
Oct 9, 2022
0bcec0a
'digest did not match' fixed
Oct 9, 2022
5d6cf8c
fixed 'diagnose'
Oct 9, 2022
a25bcb1
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Oct 16, 2022
586cac3
DSA keys are no longer supported, fixed tests
Oct 18, 2022
501b266
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Oct 18, 2022
5197b5a
Merge branch 'master' into issue-3324-openpgp-v5
ioanmo226 Nov 1, 2022
52d98cf
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Dec 21, 2022
a0de4ad
removed irrelevant test
Dec 21, 2022
8f24d4d
fix internal key
Dec 22, 2022
cafa1bf
bug fix
Dec 24, 2022
6f49724
added a separate unit test for decrypting a message encrypted with a …
Dec 24, 2022
4f6006b
fixed type of encrypted result
Dec 24, 2022
988b6c3
patch for SymEncryptedSessionKeyPacket
Dec 24, 2022
a3ad298
removed unused VerifyRes.signerFingerprints
Dec 25, 2022
a8254e0
simplify
Dec 25, 2022
3ae3936
fix test
Dec 25, 2022
bc75942
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 1, 2023
6bc4555
packing Key objects when sending to/from background
Jan 2, 2023
d9f0da6
lint fix
Jan 2, 2023
4f2f8ab
fixed fixUids
Jan 3, 2023
3d3f85a
lint fix
Jan 3, 2023
e144b57
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
rrrooommmaaa Jan 7, 2023
a649b3a
lint and formatting fixes
Jan 7, 2023
840fdb8
fixed 'no self certifications' check
Jan 7, 2023
41d3fc7
specified key 'type' option on 'generateKey'
Jan 7, 2023
7de6019
pack Key when saving revocation
Jan 8, 2023
62ccb17
fixed some decryption tests
Jan 8, 2023
936f94d
restore allow missing MDC config option
Jan 10, 2023
698c802
prettier formatting
Jan 11, 2023
f5aac3e
Added a unit test for no_mdc
Jan 11, 2023
6b3ff46
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 11, 2023
a414e21
added test for OpenPGP revocation certificate
Jan 11, 2023
6135477
wire web-stream-tools to my_key.htm
Jan 11, 2023
418acc9
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 11, 2023
ea90384
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 15, 2023
6ab398e
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 16, 2023
23a05cb
fix
Jan 16, 2023
66b6d06
use own implementation of readToEnd
Jan 16, 2023
44fe8cd
fix
Jan 17, 2023
ecc2880
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 17, 2023
11efba5
use @openpgp/web-stream-tools as a module
Jan 18, 2023
aedbf10
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 18, 2023
4022875
cleanup
Jan 18, 2023
b32f27f
test OpenPGP.js and streams from browser
Jan 18, 2023
97dc5de
more tests and fixes
Jan 19, 2023
dcde656
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 19, 2023
fe931ce
fix armoring
Jan 19, 2023
292c4a0
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 19, 2023
741238d
tidy up
Jan 19, 2023
7f65321
removed webpack
Jan 25, 2023
14bc37e
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 25, 2023
536f3ce
formatting
Jan 25, 2023
fd72898
removed stream-browserify
Jan 25, 2023
e914f96
removed tslint directives and unneeded code
Jan 25, 2023
063995d
renamed variable
Jan 25, 2023
8674f14
added comment
Jan 25, 2023
1430d69
added tests for parse exceptions
Jan 25, 2023
55fe8b9
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 26, 2023
f97ab12
refactor OpenPGPKey.revoke
Jan 26, 2023
14b869a
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 26, 2023
ce09a64
fix
Jan 26, 2023
13b186a
pack keys into binary format
Jan 27, 2023
531bc95
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 29, 2023
2eaf081
better checking of primary key flags
Jan 29, 2023
5e5f264
Verify signatures in getLastSigTime to follow previous behavior
Jan 29, 2023
13c85ac
simplify
Jan 30, 2023
4422125
simplify, reuse existing code
Jan 30, 2023
a80797e
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Jan 30, 2023
2918141
tidy up: removed unnecessary parameter
Jan 30, 2023
f743e0a
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Feb 1, 2023
c6f1280
simplify getting expiration
Feb 1, 2023
c6f15ad
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Feb 1, 2023
4e67e17
fix
Feb 2, 2023
49e0b05
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Feb 2, 2023
6814d6a
simplify getting subkey expiration
Feb 2, 2023
81df3df
fix
Feb 2, 2023
cc1369a
fix
Feb 2, 2023
beeb3de
fix
Feb 3, 2023
def173f
reuse test constant
Feb 3, 2023
f6817b3
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Feb 3, 2023
af1ef05
better preferred key detection
Feb 3, 2023
a568de9
Merge remote-tracking branch 'origin/master' into issue-3324-openpgp-v5
Feb 4, 2023
8bc07bc
finding latest expiration for expired keys
Feb 4, 2023
ca62de3
finding latest expiration for not-expired keys
Feb 4, 2023
7e8fcd8
tidying up
Feb 4, 2023
4bf8360
fix
Feb 4, 2023
4400f9d
added more tests for missing private key parameters
Feb 5, 2023
4b397c4
simplify
Feb 6, 2023
d975626
resloved potential issue with 'normalize'
Feb 6, 2023
c6d6ec4
Added a unit test for modified PgpPwd.random
Feb 6, 2023
933a1af
Added comment and removed unnecessary timestamp adjustment
Feb 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion conf/tsconfig.content_scripts.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"outDir": "../build/_/content_scripts",
"baseUrl": "../extension",
"paths": {
"dompurify": ["types/purify.d.ts"]
"dompurify": ["types/purify.d.ts"],
"openpgp": ["../node_modules/openpgp/openpgp.d.ts"],
"@openpgp/web-stream-tools": ["../node_modules/@openpgp/web-stream-tools/web-stream-tools.d.ts"]
},
"typeRoots": ["../extension/types", "../extension/js/common/core/types"]
},
Expand Down
22 changes: 22 additions & 0 deletions conf/tsconfig.streams.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ES2020",
"lib": [
"es6",
"dom"
],
"allowJs": true,
"alwaysStrict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"module": "commonjs",
"sourceMap": true,
"outDir": "../build/streams",
"skipLibCheck": true
},
"include": [
"../node_modules/@openpgp/web-stream-tools/lib/*.js"
]
}
8 changes: 7 additions & 1 deletion conf/tsconfig.test.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
"module": "commonjs",
"sourceMap": true,
"outDir": "../build/test",
"skipLibCheck": true
"skipLibCheck": true,
"paths": {
"@openpgp/web-stream-tools": [
"../node_modules/@openpgp/web-stream-tools/web-stream-tools.d.ts",
"../build/streams/streams.js"
]
}
},
"files": [
"../extension/types/node-forge.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions extension/chrome/dev/ci_unit_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Url } from '../../js/common/core/common.js';
import * as forge from 'node-forge';
import { Gmail } from '../../js/common/api/email-provider/gmail/gmail.js';
import { PgpHash } from '../../js/common/core/crypto/pgp/pgp-hash.js';
import { PgpArmor } from '../../js/common/core/crypto/pgp/pgp-armor.js';

/**
* importing all libs that are tested in ci tests
Expand All @@ -43,6 +44,7 @@ const libs: unknown[] = [
Catch,
Gmail,
PgpHash,
PgpArmor,
];
/* eslint-disable @typescript-eslint/no-explicit-any */
// add them to global scope so ci can use them
Expand Down
4 changes: 2 additions & 2 deletions extension/chrome/dev/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ Catch.try(async () => {
const pwd = prompt('Please enter encryption password');
if (pwd) {
print('encrypting..');
const encrypted = await opgp.encrypt({ armor: false, message: opgp.message.fromBinary(data), passwords: [pwd] });
save(encrypted.message.packets.write());
const encrypted = await opgp.encrypt({ format: 'binary', message: await opgp.createMessage({ binary: data }), passwords: [pwd] });
save(encrypted); // todo: test
} else {
save(data);
}
Comment on lines 123 to 130
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole page (and related html page if any) can be removed. This downloads the whole inbox at once, in a format we don't use anymore.

These days when we need a message we download it one by one, based on steps/instructions elsewhere in the code.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,23 +233,18 @@ export class EncryptedMsgMailFormatter extends BaseMailFormatter {
return attachments;
};

private encryptDataArmor = async (
data: Buf,
pwd: string | undefined,
pubs: PubkeyResult[],
signingPrv?: Key
): Promise<PgpMsgMethod.EncryptAnyArmorResult> => {
private encryptDataArmor = async (data: Buf, pwd: string | undefined, pubs: PubkeyResult[], signingPrv?: Key): Promise<PgpMsgMethod.EncryptResult> => {
const pgpPubs = pubs.filter(pub => pub.pubkey.family === 'openpgp');
const encryptAsOfDate = await this.encryptMsgAsOfDateIfSomeAreExpiredAndUserConfirmedModal(pgpPubs);
const pubsForEncryption = pubs.map(entry => entry.pubkey);
return (await MsgUtil.encryptMessage({
return await MsgUtil.encryptMessage({
pubkeys: pubsForEncryption,
signingPrv,
pwd,
data,
armor: true,
date: encryptAsOfDate,
})) as PgpMsgMethod.EncryptAnyArmorResult;
});
};

private getPwdMsgSendableBodyWithOnlineReplyMsgToken = async (
Expand Down
5 changes: 2 additions & 3 deletions extension/chrome/elements/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,9 @@ export class ComposeView extends View {
const storage = await AcctStore.get(this.acctEmail, ['sendAs', 'hide_message_password', 'fesUrl']);
this.clientConfiguration = await ClientConfiguration.newInstance(this.acctEmail);
if (this.clientConfiguration.shouldHideArmorMeta()) {
opgp.config.show_comment = false;
opgp.config.show_version = false;
opgp.config.showComment = false;
opgp.config.showVersion = false;
}
opgp.initWorker({ path: '/lib/openpgp.worker.js' });
this.pubLookup = new PubLookup(this.clientConfiguration);
this.tabId = await BrowserMsg.requiredTabId();
this.factory = new XssSafeFactory(this.acctEmail, this.tabId);
Expand Down
2 changes: 1 addition & 1 deletion extension/chrome/settings/modules/my_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ View.run(
if (!(await Ui.modal.confirm(revokeConfirmMsg))) {
return;
}
const revokedArmored = await KeyUtil.revoke(prv);
const revokedArmored = await KeyUtil.getOrCreateRevocationCertificate(prv);
if (!revokedArmored) {
await Ui.modal.error(`Could not produce revocation cert (empty)`);
return;
Expand Down
4 changes: 2 additions & 2 deletions extension/chrome/settings/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ export class SetupView extends View {
this.storage.email_provider = this.storage.email_provider || 'gmail';
this.clientConfiguration = await ClientConfiguration.newInstance(this.acctEmail);
if (this.clientConfiguration.shouldHideArmorMeta() && typeof opgp !== 'undefined') {
opgp.config.show_comment = false;
opgp.config.show_version = false;
opgp.config.showComment = false;
opgp.config.showVersion = false;
}
this.pubLookup = new PubLookup(this.clientConfiguration);
if (this.clientConfiguration.usesKeyManager() && this.idToken) {
Expand Down
3 changes: 0 additions & 3 deletions extension/js/background_page/background_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { GoogleAuth } from '../common/api/email-provider/gmail/google-auth.js';
import { Bm, BrowserMsg } from '../common/browser/browser-msg.js';
import { emailKeyIndex } from '../common/core/common.js';
import { VERSION } from '../common/core/const.js';
import { opgp } from '../common/core/crypto/pgp/openpgpjs-custom.js';
import { ExpirationCache } from '../common/core/expiration-cache.js';
import { processAndStoreKeysFromEkmLocally, getLocalKeyExpiration } from '../common/helpers.js';
import { Catch } from '../common/platform/catch.js';
Expand All @@ -20,8 +19,6 @@ import { migrateGlobal, moveContactsToEmailsAndPubkeys, updateOpgpRevocations, u

console.info('background_process.js starting');

opgp.initWorker({ path: '/lib/openpgp.worker.js' });

tomholub marked this conversation as resolved.
Show resolved Hide resolved
(async () => {
let db: IDBDatabase;
let storage: GlobalStoreDict;
Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/browser/browser-msg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ export class BrowserMsg {
BrowserMsg.bgAddListener('pgpMsgDiagnosePubkeys', MsgUtil.diagnosePubkeys);
BrowserMsg.bgAddListener('pgpMsgDecrypt', MsgUtil.decryptMessage);
BrowserMsg.bgAddListener('pgpMsgVerifyDetached', MsgUtil.verifyDetached);
BrowserMsg.bgAddListener('pgpMsgType', MsgUtil.type);
BrowserMsg.bgAddListener('pgpMsgType', async (r: Bm.PgpMsgType) => MsgUtil.type(r));
BrowserMsg.bgAddListener('saveFetchedPubkeys', saveFetchedPubkeysIfNewerThanInStorage);
BrowserMsg.bgAddListener('pgpKeyBinaryToArmored', async (r: Bm.PgpKeyBinaryToArmored) => ({
keys: await KeyUtil.parseAndArmorKeys(r.binaryKeysData),
Expand Down
39 changes: 24 additions & 15 deletions extension/js/common/core/crypto/key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MsgBlockParser } from '../msg-block-parser.js';
import { PgpArmor } from './pgp/pgp-armor.js';
import { opgp } from './pgp/openpgpjs-custom.js';
import { OpenPGPKey } from './pgp/openpgp-key.js';
import type * as OpenPGP from 'openpgp';
import { SmimeKey } from './smime/smime-key.js';
import { MsgBlock } from '../msg-block.js';
import { EmailParts } from '../common.js';
Expand Down Expand Up @@ -95,7 +96,7 @@ export interface KeyInfoWithIdentityAndOptionalPp extends KeyInfoWithIdentity {

export type KeyAlgo = 'curve25519' | 'rsa2048' | 'rsa3072' | 'rsa4096';

export type PrvPacket = OpenPGP.packet.SecretKey | OpenPGP.packet.SecretSubkey;
export type PrvPacket = OpenPGP.SecretKeyPacket | OpenPGP.SecretSubkeyPacket;

export class UnexpectedKeyTypeError extends Error {}

Expand Down Expand Up @@ -203,7 +204,7 @@ export class KeyUtil {
allErr: Error[] = [];
let uncheckedOpgpKeyCount = 0;
try {
const { keys, err } = await opgp.key.read(key);
const keys = await opgp.readKeys({ binaryKeys: key }); // todo: opgp.readKey ?
Comment on lines -206 to +207
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ok to me as implemented, is the todo still current?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new opgp.readKeys function differs in that it doesn't wrap each new PrivateKey/new PublicKey constructor in a try/catch block unlike the 4.10.10 implementation. So if we stumble on the some non-last key, the remaining keys won't be processed.
That got me confused

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. Not ideal but ok to proceed as is and file an issue.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uncheckedOpgpKeyCount = keys.length;
for (const key of keys) {
try {
Expand All @@ -221,9 +222,9 @@ export class KeyUtil {
allErr.push(e as Error);
}
}
if (err) {
/* todo: re-throw? if (err) {
allErr.push(...err);
}
} */
tomholub marked this conversation as resolved.
Show resolved Hide resolved
} catch (e) {
allErr.push(e as Error);
}
Expand All @@ -246,14 +247,21 @@ export class KeyUtil {
throw new Error(err.length ? err.map((e, i) => i + 1 + '. ' + e.message).join('\n') : 'Should not happen: no keys and no errors.');
};

public static armor = (pubkey: Key): string => {
const armored = (pubkey as unknown as { rawArmored: string }).rawArmored;
public static armor = (key: Key): string => {
const armored = (key as unknown as { rawArmored: string }).rawArmored;
if (!armored) {
throw new Error('The Key object has no rawArmored field.');
}
return armored;
};

// remove crypto-library objects (useful when sending the object to/from background)
public static pack = (key: Key): void => {
if (key.family === 'openpgp') {
OpenPGPKey.pack(key);
}
};

public static diagnose = async (key: Key, passphrase: string): Promise<Map<string, string>> => {
let result = new Map<string, string>();
result.set(`Key type`, key.family);
Expand Down Expand Up @@ -303,16 +311,17 @@ export class KeyUtil {
};

// todo - this should be made to tolerate smime keys
public static normalize = async (armored: string): Promise<{ normalized: string; keys: OpenPGP.key.Key[] }> => {
public static normalize = async (type: 'publicKey' | 'privateKey', armored: string): Promise<{ normalized: string; keys: OpenPGP.Key[] }> => {
try {
let keys: OpenPGP.key.Key[] = [];
let keys: OpenPGP.Key[] = [];
armored = PgpArmor.normalize(armored, 'key');
if (RegExp(PgpArmor.headers('publicKey', 're').begin).test(armored)) {
keys = (await opgp.key.readArmored(armored)).keys;
keys = await opgp.readKeys({ armoredKeys: armored });
} else if (RegExp(PgpArmor.headers('privateKey', 're').begin).test(armored)) {
keys = (await opgp.key.readArmored(armored)).keys;
keys = await opgp.readKeys({ armoredKeys: armored });
} else if (RegExp(PgpArmor.headers('encryptedMsg', 're').begin).test(armored)) {
keys = [new opgp.key.Key((await opgp.message.readArmored(armored)).packets)];
const packets = (await opgp.readMessage({ armoredMessage: armored })).packets;
keys = [type === 'publicKey' ? new opgp.PublicKey(packets) : new opgp.PrivateKey(packets)];
}
for (const k of keys) {
for (const u of k.users) {
Expand Down Expand Up @@ -350,7 +359,7 @@ export class KeyUtil {
public static decrypt = async (
key: Key,
passphrase: string,
optionalKeyid?: OpenPGP.Keyid,
optionalKeyid?: OpenPGP.KeyID,
optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'
): Promise<boolean> => {
if (key.family === 'openpgp') {
Expand Down Expand Up @@ -385,11 +394,11 @@ export class KeyUtil {
}
};

public static revoke = async (key: Key): Promise<string | undefined> => {
public static getOrCreateRevocationCertificate = async (key: Key): Promise<string | undefined> => {
if (key.family === 'openpgp') {
return await OpenPGPKey.revoke(key);
return await OpenPGPKey.getOrCreateRevocationCertificate(key);
} else {
throw new Error(`KeyUtil.revoke does not support key family ${key.family}`);
throw new Error(`KeyUtil.getOrCreateRevocationCertificate does not support key family ${key.family}`);
}
};

Expand Down
Loading