mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-17 18:44:45 +02:00
Mobile,Desktop: Fix unable to change incorrect decryption password if the same as the master password (#11026)
This commit is contained in:
parent
69168f1ec2
commit
79773dab95
@ -917,6 +917,7 @@ packages/lib/commands/historyForward.js
|
|||||||
packages/lib/commands/index.js
|
packages/lib/commands/index.js
|
||||||
packages/lib/commands/openMasterPasswordDialog.js
|
packages/lib/commands/openMasterPasswordDialog.js
|
||||||
packages/lib/commands/synchronize.js
|
packages/lib/commands/synchronize.js
|
||||||
|
packages/lib/components/EncryptionConfigScreen/utils.test.js
|
||||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||||
packages/lib/components/shared/NoteList/getEmptyFolderMessage.js
|
packages/lib/components/shared/NoteList/getEmptyFolderMessage.js
|
||||||
packages/lib/components/shared/config/config-shared.js
|
packages/lib/components/shared/config/config-shared.js
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -894,6 +894,7 @@ packages/lib/commands/historyForward.js
|
|||||||
packages/lib/commands/index.js
|
packages/lib/commands/index.js
|
||||||
packages/lib/commands/openMasterPasswordDialog.js
|
packages/lib/commands/openMasterPasswordDialog.js
|
||||||
packages/lib/commands/synchronize.js
|
packages/lib/commands/synchronize.js
|
||||||
|
packages/lib/components/EncryptionConfigScreen/utils.test.js
|
||||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||||
packages/lib/components/shared/NoteList/getEmptyFolderMessage.js
|
packages/lib/components/shared/NoteList/getEmptyFolderMessage.js
|
||||||
packages/lib/components/shared/config/config-shared.js
|
packages/lib/components/shared/config/config-shared.js
|
||||||
|
88
packages/lib/components/EncryptionConfigScreen/utils.test.ts
Normal file
88
packages/lib/components/EncryptionConfigScreen/utils.test.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import MasterKey from '../../models/MasterKey';
|
||||||
|
import EncryptionService, { EncryptionMethod } from '../../services/e2ee/EncryptionService';
|
||||||
|
import { MasterKeyEntity } from '../../services/e2ee/types';
|
||||||
|
import { setEncryptionEnabled } from '../../services/synchronizer/syncInfoUtils';
|
||||||
|
import { setupDatabaseAndSynchronizer, switchClient } from '../../testing/test-utils';
|
||||||
|
import { usePasswordChecker } from './utils';
|
||||||
|
import { renderHook } from '@testing-library/react-hooks';
|
||||||
|
|
||||||
|
interface WrappedPasswordCheckerProps {
|
||||||
|
masterKeys: MasterKeyEntity[];
|
||||||
|
activeMasterKeyId: string;
|
||||||
|
masterPassword: string;
|
||||||
|
passwords: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useWrappedPasswordChecker = ({
|
||||||
|
masterKeys = [],
|
||||||
|
activeMasterKeyId = '',
|
||||||
|
masterPassword = '',
|
||||||
|
passwords = {},
|
||||||
|
}: WrappedPasswordCheckerProps) => usePasswordChecker(
|
||||||
|
masterKeys,
|
||||||
|
activeMasterKeyId,
|
||||||
|
masterPassword,
|
||||||
|
passwords,
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('EncryptionConfigScreen/utils', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await setupDatabaseAndSynchronizer(0);
|
||||||
|
await switchClient(0);
|
||||||
|
setEncryptionEnabled(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not mark keys as master password keys if the master password is incorrect for that key', async () => {
|
||||||
|
const makeMasterKey = async (password: string) => {
|
||||||
|
const result = await EncryptionService.instance().generateMasterKey(password, {
|
||||||
|
encryptionMethod: EncryptionMethod.SJCL4,
|
||||||
|
});
|
||||||
|
return await MasterKey.save(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
const activeMasterKey = await makeMasterKey('master-password');
|
||||||
|
const secondaryMasterKey = await makeMasterKey('some other password');
|
||||||
|
const masterKeys = [
|
||||||
|
activeMasterKey,
|
||||||
|
secondaryMasterKey,
|
||||||
|
];
|
||||||
|
|
||||||
|
const initialProps = {
|
||||||
|
masterKeys,
|
||||||
|
activeMasterKeyId: activeMasterKey.id,
|
||||||
|
masterPassword: 'master-password',
|
||||||
|
passwords: {
|
||||||
|
[activeMasterKey.id]: 'master-password',
|
||||||
|
[secondaryMasterKey.id]: 'some other password',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const hook = renderHook(useWrappedPasswordChecker, {
|
||||||
|
initialProps,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Different password from the master password should cause the secondary key
|
||||||
|
// to be marked as not using the master password.
|
||||||
|
await hook.waitFor(() => {
|
||||||
|
expect(hook.result.current.masterPasswordKeys).toMatchObject({
|
||||||
|
[activeMasterKey.id]: true,
|
||||||
|
[secondaryMasterKey.id]: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Same password as the master password but fails to decrypt: Should not be marked
|
||||||
|
// as using the master password.
|
||||||
|
hook.rerender({
|
||||||
|
...initialProps,
|
||||||
|
passwords: {
|
||||||
|
...initialProps.passwords,
|
||||||
|
[secondaryMasterKey.id]: 'primary',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await hook.waitFor(() => {
|
||||||
|
expect(hook.result.current.masterPasswordKeys).toMatchObject({
|
||||||
|
[activeMasterKey.id]: true,
|
||||||
|
[secondaryMasterKey.id]: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -160,15 +160,20 @@ export const usePasswordChecker = (masterKeys: MasterKeyEntity[], activeMasterKe
|
|||||||
const newPasswordChecks: PasswordChecks = {};
|
const newPasswordChecks: PasswordChecks = {};
|
||||||
const newMasterPasswordKeys: PasswordChecks = {};
|
const newMasterPasswordKeys: PasswordChecks = {};
|
||||||
|
|
||||||
|
const masterPasswordOk = masterPassword ? await masterPasswordIsValid(masterPassword, masterKeys.find(mk => mk.id === activeMasterKeyId)) : true;
|
||||||
|
newPasswordChecks['master'] = masterPasswordOk;
|
||||||
|
|
||||||
for (let i = 0; i < masterKeys.length; i++) {
|
for (let i = 0; i < masterKeys.length; i++) {
|
||||||
const mk = masterKeys[i];
|
const mk = masterKeys[i];
|
||||||
const password = await findMasterKeyPassword(EncryptionService.instance(), mk, passwords);
|
const password = await findMasterKeyPassword(EncryptionService.instance(), mk, passwords);
|
||||||
const ok = password ? await EncryptionService.instance().checkMasterKeyPassword(mk, password) : false;
|
const ok = password ? await EncryptionService.instance().checkMasterKeyPassword(mk, password) : false;
|
||||||
newPasswordChecks[mk.id] = ok;
|
newPasswordChecks[mk.id] = ok;
|
||||||
newMasterPasswordKeys[mk.id] = password === masterPassword;
|
|
||||||
|
// Even if the password matches the master password, it isn't a master password key if the
|
||||||
|
// master password can't decrypt this key.
|
||||||
|
newMasterPasswordKeys[mk.id] = password === masterPassword && (ok || !masterPasswordOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
newPasswordChecks['master'] = masterPassword ? await masterPasswordIsValid(masterPassword, masterKeys.find(mk => mk.id === activeMasterKeyId)) : true;
|
|
||||||
|
|
||||||
if (event.cancelled) return;
|
if (event.cancelled) return;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user