From 054b98884445ba9e88341ef0441fc65c6f0b9c6f Mon Sep 17 00:00:00 2001 From: Sagnik Mandal Date: Tue, 27 Feb 2024 16:44:55 +0530 Subject: [PATCH 1/7] Desktop: Fixes #9985: Filter Sync Target Info Logs --- packages/lib/Synchronizer.ts | 5 ++-- .../synchronizer/syncInfoUtils.test.ts | 26 +++++++++++++++++++ .../services/synchronizer/syncInfoUtils.ts | 16 ++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/lib/Synchronizer.ts b/packages/lib/Synchronizer.ts index 4c4b73f5af5..f82d3957dfd 100644 --- a/packages/lib/Synchronizer.ts +++ b/packages/lib/Synchronizer.ts @@ -451,7 +451,7 @@ export default class Synchronizer { try { let remoteInfo = await fetchSyncInfo(this.api()); - logger.info('Sync target remote info:', remoteInfo); + logger.info('Sync target remote info:', remoteInfo.filterSyncInfo()); eventManager.emit(EventName.SessionEstablished); let syncTargetIsNew = false; @@ -471,8 +471,7 @@ export default class Synchronizer { if (appVersion !== 'unknown') checkIfCanSync(remoteInfo, appVersion); let localInfo = await localSyncInfo(); - - logger.info('Sync target local info:', localInfo); + logger.info('Sync target local info:', localInfo.filterSyncInfo()); localInfo = await this.setPpkIfNotExist(localInfo, remoteInfo); diff --git a/packages/lib/services/synchronizer/syncInfoUtils.test.ts b/packages/lib/services/synchronizer/syncInfoUtils.test.ts index 869408b6fa2..5835c80882e 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.test.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.test.ts @@ -200,6 +200,32 @@ describe('syncInfoUtils', () => { logger.enabled = true; }); + it('should filter unnecessary sync info', async () => { + const syncInfo = new SyncInfo(); + syncInfo.masterKeys = [{ + id: '1', + content: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', + checksum: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', + }]; + syncInfo.ppk = { + id: '1', + publicKey: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', + privateKey: { + encryptionMethod: 1, + ciphertext: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', + }, + createdTime: 0, + keySize: 0, + }; + const filteredSyncInfo = syncInfo.filterSyncInfo(); + + expect(filteredSyncInfo.masterKeys_[0].content).toBeUndefined(); + expect(filteredSyncInfo.masterKeys_[0].checksum).toBeUndefined(); + + expect(filteredSyncInfo.ppk_.value.publicKey).toBe('longstringverylongstringlongstringverylo'); + expect(filteredSyncInfo.ppk_.value.privateKey.ciphertext).toBe('longstringverylongst...stringverylongstring'); + }); + test.each([ ['1.0.0', '1.0.4', true], ['1.0.0', '0.0.5', false], diff --git a/packages/lib/services/synchronizer/syncInfoUtils.ts b/packages/lib/services/synchronizer/syncInfoUtils.ts index 2042aaf02c6..f74d79f751c 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.ts @@ -240,6 +240,22 @@ export class SyncInfo { }; } + public filterSyncInfo() { + const filtered = JSON.parse(JSON.stringify(this)); + + // Filter content and checksum properties from master keys + filtered.masterKeys_ = filtered.masterKeys_.map((mk: MasterKeyEntity) => { + delete mk.content; + delete mk.checksum; + return mk; + }); + + // Truncate the private key and public key + filtered.ppk_.value.privateKey.ciphertext = `${filtered.ppk_.value.privateKey.ciphertext.substr(0, 20)}...${filtered.ppk_.value.privateKey.ciphertext.substr(-20)}`; + filtered.ppk_.value.publicKey = filtered.ppk_.value.publicKey.substr(0, 40); + return filtered; + } + public serialize(): string { return JSON.stringify(this.toObject(), null, '\t'); } From b319fdd269baeb8b35a16a19dc55bb0b09ad4e6b Mon Sep 17 00:00:00 2001 From: Sagnik Mandal Date: Tue, 27 Feb 2024 17:14:19 +0530 Subject: [PATCH 2/7] Only Filter if values are present --- .../lib/services/synchronizer/syncInfoUtils.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/lib/services/synchronizer/syncInfoUtils.ts b/packages/lib/services/synchronizer/syncInfoUtils.ts index f74d79f751c..ae3c2fc69b6 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.ts @@ -244,15 +244,19 @@ export class SyncInfo { const filtered = JSON.parse(JSON.stringify(this)); // Filter content and checksum properties from master keys - filtered.masterKeys_ = filtered.masterKeys_.map((mk: MasterKeyEntity) => { - delete mk.content; - delete mk.checksum; - return mk; - }); + if (filtered.masterKeys_) { + filtered.masterKeys_ = filtered.masterKeys_.map((mk: MasterKeyEntity) => { + if (mk.content) delete mk.content; + if (mk.checksum) delete mk.checksum; + return mk; + }); + } // Truncate the private key and public key - filtered.ppk_.value.privateKey.ciphertext = `${filtered.ppk_.value.privateKey.ciphertext.substr(0, 20)}...${filtered.ppk_.value.privateKey.ciphertext.substr(-20)}`; - filtered.ppk_.value.publicKey = filtered.ppk_.value.publicKey.substr(0, 40); + if (filtered.ppk_.value) { + filtered.ppk_.value.privateKey.ciphertext = `${filtered.ppk_.value.privateKey.ciphertext.substr(0, 20)}...${filtered.ppk_.value.privateKey.ciphertext.substr(-20)}`; + filtered.ppk_.value.publicKey = filtered.ppk_.value.publicKey.substr(0, 40); + } return filtered; } From 0e79f4f3ceabfdd99b71ea8943cfbfed455d9447 Mon Sep 17 00:00:00 2001 From: Sagnik Mandal Date: Tue, 27 Feb 2024 17:44:09 +0530 Subject: [PATCH 3/7] Disable Spellcheck for test --- packages/lib/services/synchronizer/syncInfoUtils.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/lib/services/synchronizer/syncInfoUtils.test.ts b/packages/lib/services/synchronizer/syncInfoUtils.test.ts index 5835c80882e..9b6bd601b54 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.test.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.test.ts @@ -200,6 +200,7 @@ describe('syncInfoUtils', () => { logger.enabled = true; }); + // cSpell:disable it('should filter unnecessary sync info', async () => { const syncInfo = new SyncInfo(); syncInfo.masterKeys = [{ @@ -225,6 +226,7 @@ describe('syncInfoUtils', () => { expect(filteredSyncInfo.ppk_.value.publicKey).toBe('longstringverylongstringlongstringverylo'); expect(filteredSyncInfo.ppk_.value.privateKey.ciphertext).toBe('longstringverylongst...stringverylongstring'); }); + // cSpell:enable test.each([ ['1.0.0', '1.0.4', true], From 441b85ea723c3f0cf61131527d36aca6534e97f4 Mon Sep 17 00:00:00 2001 From: Sagnik Mandal Date: Tue, 27 Feb 2024 20:58:33 +0530 Subject: [PATCH 4/7] Compare with the complete object --- .../synchronizer/syncInfoUtils.test.ts | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/lib/services/synchronizer/syncInfoUtils.test.ts b/packages/lib/services/synchronizer/syncInfoUtils.test.ts index 9b6bd601b54..b5222ffefa1 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.test.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.test.ts @@ -219,12 +219,33 @@ describe('syncInfoUtils', () => { keySize: 0, }; const filteredSyncInfo = syncInfo.filterSyncInfo(); - - expect(filteredSyncInfo.masterKeys_[0].content).toBeUndefined(); - expect(filteredSyncInfo.masterKeys_[0].checksum).toBeUndefined(); - - expect(filteredSyncInfo.ppk_.value.publicKey).toBe('longstringverylongstringlongstringverylo'); - expect(filteredSyncInfo.ppk_.value.privateKey.ciphertext).toBe('longstringverylongst...stringverylongstring'); + const originalSyncInfo = syncInfo.toObject(); + + expect(filteredSyncInfo).toEqual({ + activeMasterKeyId_: originalSyncInfo.activeMasterKeyId, + appMinVersion_: originalSyncInfo.appMinVersion, + e2ee_: originalSyncInfo.e2ee, + version_: originalSyncInfo.version, + masterKeys_: [ + // Content & Checksum are removed + { id: '1' }, + ], + ppk_: { + value: { + // Public Key is truncated to 40 characters + publicKey: 'longstringverylongstringlongstringverylo', + privateKey: { + // Private Key is truncated to first and last 20 characters + ciphertext: 'longstringverylongst...stringverylongstring', + encryptionMethod: 1, + }, + id: '1', + createdTime: 0, + keySize: 0, + }, + updatedTime: originalSyncInfo.ppk.updatedTime, + }, + }); }); // cSpell:enable From 612b705e105da97a1049e3c4c94f18fedcb0a96f Mon Sep 17 00:00:00 2001 From: Sagnik Mandal Date: Tue, 27 Feb 2024 21:54:20 +0530 Subject: [PATCH 5/7] Remove unnecessary check --- packages/lib/services/synchronizer/syncInfoUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lib/services/synchronizer/syncInfoUtils.ts b/packages/lib/services/synchronizer/syncInfoUtils.ts index ae3c2fc69b6..91f0a8671cf 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.ts @@ -246,8 +246,8 @@ export class SyncInfo { // Filter content and checksum properties from master keys if (filtered.masterKeys_) { filtered.masterKeys_ = filtered.masterKeys_.map((mk: MasterKeyEntity) => { - if (mk.content) delete mk.content; - if (mk.checksum) delete mk.checksum; + delete mk.content; + delete mk.checksum; return mk; }); } From 320a8ccb0311a2c2dd3d8a44d4feb3876ddb4082 Mon Sep 17 00:00:00 2001 From: Sagnik Mandal Date: Tue, 27 Feb 2024 22:33:36 +0530 Subject: [PATCH 6/7] Update publicKey truncation & change test to use static data --- .../synchronizer/syncInfoUtils.test.ts | 102 ++++++++++++------ .../services/synchronizer/syncInfoUtils.ts | 2 +- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/packages/lib/services/synchronizer/syncInfoUtils.test.ts b/packages/lib/services/synchronizer/syncInfoUtils.test.ts index b5222ffefa1..c5dc9936191 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.test.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.test.ts @@ -202,49 +202,83 @@ describe('syncInfoUtils', () => { // cSpell:disable it('should filter unnecessary sync info', async () => { - const syncInfo = new SyncInfo(); - syncInfo.masterKeys = [{ - id: '1', - content: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', - checksum: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', - }]; - syncInfo.ppk = { - id: '1', - publicKey: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', - privateKey: { - encryptionMethod: 1, - ciphertext: 'longstringverylongstringlongstringverylongstringlongstringverylongstring', + const initialData = { + 'version': 3, + 'e2ee': { + 'value': true, + 'updatedTime': 0, }, - createdTime: 0, - keySize: 0, + 'activeMasterKeyId': { + 'value': '400227d2222c4d3bb7346514861c643b', + 'updatedTime': 0, + }, + 'masterKeys': [ + { + 'id': '400227d8a77c4d3bb7346514861c643b', + 'created_time': 1515008161362, + 'updated_time': 1708103706234, + 'source_application': 'net.cozic.joplin-desktop', + 'encryption_method': 4, + 'checksum': '', + 'content': '{"iv":"M1uezlW1Pu1g3dwrCTqcHg==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"0dqWvU/PUVQ=","ct":"wHXN5pk1s7qKX+2Y9puEGZGkojI1Pvc+TvZUKC6QCfwxtMK6C1Hmgvm53vAaeCMcCXPvGVLo9JwqINFhEgb0ux+KUFcCqgT1pNO2Sf/hJsH8PjaUvl0kwpC511zdnvY7Hk3WIpgXVKUevsQt9TkMK5e8y1JMsuuTD3fW7bEiv/ehe4CBSQ9eH1tWjr1qQ=="}', + 'hasBeenUsed': true, + }, + ], + 'ppk': { + 'value': { + 'id': 'SNQ5ZCs61KDVUW2qqqqHd3', + 'keySize': 2048, + 'privateKey': { + 'encryptionMethod': 4, + 'ciphertext': '{"iv":"Z2y11b4nCYvpmQ9gvxELug==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"0dqWvU/PUVQ=","ct":"8CvjYayXMpLsrAMwtu18liRfewKfZVpRlC0D0I2FYziyFhRf4Cjqi2+Uy8kIC8au7oBSBUnNU6jd04ooNozneKv2MzkhbGlXo3izxqCMVHboqa2vkPWbBAxGlvUYQUg213xG61FjZ19ZJdpti+AQy7qpQU7/h5kyC0iJ2aXG5TIGcBuDq3lbGAVfG/RlL/abMKLYb8KouFYAJe+0bUajUXa1KJsey+eD+2hFVc+nAxKOLe1UoZysB77Lq43DRTBFGH2gTSC1zOXxuZeSbFPPN0Cj+FvV7D5pF9LhUSLPDsIiRwF/q+E506YgDjirSZAvW1Y2EEM22F2Mh0I0pbVPFXhhBafqPLRwXmUGULCnA64gkGwctK5mEs985VVSrpQ0nMvf/drg2vUQrJ3exgl43ddVSOCjeJuF7F06IBL5FQ34iAujsOheRNvlWtG9xm008Vc19NxvhtzIl1RO7XLXrrTBzbFHDrcHjda/xNWNEKwU/LZrH0xPgwEcwBmLItvy/NojI/JKNeck8R431QWooFb7cTplO4qsgCQNL9MJ9avpmNSXJAUQx8VnifKVbzcY4T7X7TmJWSrpvBWV8MLfi3TOF4kahR75vg47kCrMbthFMw5bvrjvMmGOtyKxheqbS5IlSnSSz5x7wIVz0g3vzMbcbb5rF5MuzNhU97wNiz3L1Aonjmnu8r3vCyXTB/4GSiwYH7KfixwYM68T4crqJ0VneNy+owznCdJQXnG4cmjxek1wmJMEmurQ1JtANNv/m43gzoqd62V6Dq05vLJF+n7CS9HgJ3FTqYVCZLGGYrSilIYnEjhdaBpkcnFrCitbfYj+IpNC6eN6qg2hpGAbmKId7RLOGwJyda0jkuNP9mTqWOF+6eYn8Q+Y3YIY"}', + }, + 'publicKey': '-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAiSTY5wBscae/WmU3PfVP5FYQiuTi5V7BjPcge/6pXvgF3zwe43uy\nTWdzO2YgK/a8f3H507clcGlZN4e0e1jZ/rh4lMfaN\nugfNo0RAvuwn8Yniqfb69reygJywbFBIauxbBpVKbc21MLuCbPkVFjKG7qGNYdF4\nc17mQ8nQsbFPZcuvxsZvgvvbza1q0rqVETdDUClyIrY8plAjMgTKCRwq2gafP6eX\nWpkENAyIbOFxSKXjWy0yFidvZfYLz4mIRwIDAQAB\n-----END RSA PUBLIC KEY-----', + 'createdTime': 1633274368892, + }, + 'updatedTime': 1633274368892, + }, + 'appMinVersion': '0.0.0', }; + + const syncInfo = new SyncInfo(); + syncInfo.load(JSON.stringify(initialData)); + const filteredSyncInfo = syncInfo.filterSyncInfo(); - const originalSyncInfo = syncInfo.toObject(); expect(filteredSyncInfo).toEqual({ - activeMasterKeyId_: originalSyncInfo.activeMasterKeyId, - appMinVersion_: originalSyncInfo.appMinVersion, - e2ee_: originalSyncInfo.e2ee, - version_: originalSyncInfo.version, - masterKeys_: [ - // Content & Checksum are removed - { id: '1' }, + 'activeMasterKeyId_': { + 'updatedTime': 0, + 'value': '400227d2222c4d3bb7346514861c643b', + }, + 'appMinVersion_': '0.0.0', + 'e2ee_': { + 'updatedTime': 0, + 'value': true, + }, + 'masterKeys_': [ + { + 'created_time': 1515008161362, + 'encryption_method': 4, + 'hasBeenUsed': true, + 'id': '400227d8a77c4d3bb7346514861c643b', + 'source_application': 'net.cozic.joplin-desktop', + 'updated_time': 1708103706234, + }, ], - ppk_: { - value: { - // Public Key is truncated to 40 characters - publicKey: 'longstringverylongstringlongstringverylo', - privateKey: { - // Private Key is truncated to first and last 20 characters - ciphertext: 'longstringverylongst...stringverylongstring', - encryptionMethod: 1, + 'ppk_': { + 'updatedTime': 1633274368892, + 'value': { + 'createdTime': 1633274368892, + 'id': 'SNQ5ZCs61KDVUW2qqqqHd3', + 'keySize': 2048, + 'privateKey': { + 'ciphertext': '{"iv":"Z2y11b4nCYvpm...TqWOF+6eYn8Q+Y3YIY"}', + 'encryptionMethod': 4, }, - id: '1', - createdTime: 0, - keySize: 0, + 'publicKey': '-----BEGIN RSA PUBLI... RSA PUBLIC KEY-----', }, - updatedTime: originalSyncInfo.ppk.updatedTime, }, + 'version_': 3, }); }); // cSpell:enable diff --git a/packages/lib/services/synchronizer/syncInfoUtils.ts b/packages/lib/services/synchronizer/syncInfoUtils.ts index 91f0a8671cf..46cc44a68b5 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.ts @@ -255,7 +255,7 @@ export class SyncInfo { // Truncate the private key and public key if (filtered.ppk_.value) { filtered.ppk_.value.privateKey.ciphertext = `${filtered.ppk_.value.privateKey.ciphertext.substr(0, 20)}...${filtered.ppk_.value.privateKey.ciphertext.substr(-20)}`; - filtered.ppk_.value.publicKey = filtered.ppk_.value.publicKey.substr(0, 40); + filtered.ppk_.value.publicKey = `${filtered.ppk_.value.publicKey.substr(0, 20)}...${filtered.ppk_.value.publicKey.substr(-20)}`; } return filtered; } From 32d6dfaf176dbd5f8f922a9d86d69f4c1ca3c2ed Mon Sep 17 00:00:00 2001 From: Sagnik Mandal Date: Tue, 27 Feb 2024 22:51:57 +0530 Subject: [PATCH 7/7] Make the filter consistent --- .../services/synchronizer/syncInfoUtils.test.ts | 14 +++++++------- .../lib/services/synchronizer/syncInfoUtils.ts | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/lib/services/synchronizer/syncInfoUtils.test.ts b/packages/lib/services/synchronizer/syncInfoUtils.test.ts index c5dc9936191..2dfd307d159 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.test.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.test.ts @@ -246,16 +246,16 @@ describe('syncInfoUtils', () => { const filteredSyncInfo = syncInfo.filterSyncInfo(); expect(filteredSyncInfo).toEqual({ - 'activeMasterKeyId_': { + 'activeMasterKeyId': { 'updatedTime': 0, 'value': '400227d2222c4d3bb7346514861c643b', }, - 'appMinVersion_': '0.0.0', - 'e2ee_': { + 'appMinVersion': '0.0.0', + 'e2ee': { 'updatedTime': 0, 'value': true, }, - 'masterKeys_': [ + 'masterKeys': [ { 'created_time': 1515008161362, 'encryption_method': 4, @@ -265,7 +265,7 @@ describe('syncInfoUtils', () => { 'updated_time': 1708103706234, }, ], - 'ppk_': { + 'ppk': { 'updatedTime': 1633274368892, 'value': { 'createdTime': 1633274368892, @@ -275,10 +275,10 @@ describe('syncInfoUtils', () => { 'ciphertext': '{"iv":"Z2y11b4nCYvpm...TqWOF+6eYn8Q+Y3YIY"}', 'encryptionMethod': 4, }, - 'publicKey': '-----BEGIN RSA PUBLI... RSA PUBLIC KEY-----', + 'publicKey': '-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCA...', }, }, - 'version_': 3, + 'version': 3, }); }); // cSpell:enable diff --git a/packages/lib/services/synchronizer/syncInfoUtils.ts b/packages/lib/services/synchronizer/syncInfoUtils.ts index 46cc44a68b5..c2d6dcfab44 100644 --- a/packages/lib/services/synchronizer/syncInfoUtils.ts +++ b/packages/lib/services/synchronizer/syncInfoUtils.ts @@ -241,11 +241,11 @@ export class SyncInfo { } public filterSyncInfo() { - const filtered = JSON.parse(JSON.stringify(this)); + const filtered = JSON.parse(JSON.stringify(this.toObject())); // Filter content and checksum properties from master keys - if (filtered.masterKeys_) { - filtered.masterKeys_ = filtered.masterKeys_.map((mk: MasterKeyEntity) => { + if (filtered.masterKeys) { + filtered.masterKeys = filtered.masterKeys.map((mk: MasterKeyEntity) => { delete mk.content; delete mk.checksum; return mk; @@ -253,9 +253,9 @@ export class SyncInfo { } // Truncate the private key and public key - if (filtered.ppk_.value) { - filtered.ppk_.value.privateKey.ciphertext = `${filtered.ppk_.value.privateKey.ciphertext.substr(0, 20)}...${filtered.ppk_.value.privateKey.ciphertext.substr(-20)}`; - filtered.ppk_.value.publicKey = `${filtered.ppk_.value.publicKey.substr(0, 20)}...${filtered.ppk_.value.publicKey.substr(-20)}`; + if (filtered.ppk.value) { + filtered.ppk.value.privateKey.ciphertext = `${filtered.ppk.value.privateKey.ciphertext.substr(0, 20)}...${filtered.ppk.value.privateKey.ciphertext.substr(-20)}`; + filtered.ppk.value.publicKey = `${filtered.ppk.value.publicKey.substr(0, 40)}...`; } return filtered; }