check password

This commit is contained in:
fyears 2021-11-08 00:39:17 +08:00
parent cc0c4fe224
commit 7fc38a942a
3 changed files with 85 additions and 7 deletions

View File

@ -8,6 +8,9 @@ import {
const DEFAULT_ITER = 10000;
// base32.stringify(Buffer.from('Salted__'))
export const MAGIC_ENCRYPTED_PREFIX_BASE32 = "KNQWY5DFMRPV";
const getKeyIVFromPassword = async (
salt: Uint8Array,
password: string,

View File

@ -26,8 +26,8 @@ import {
insertSyncPlanRecord,
} from "./localdb";
import type { SyncStatusType } from "./sync";
import { getSyncPlan, doActualSync } from "./sync";
import type { SyncStatusType, PasswordCheckType } from "./sync";
import { isPasswordOk, getSyncPlan, doActualSync } from "./sync";
import {
DEFAULT_S3_CONFIG,
getS3Client,
@ -98,7 +98,17 @@ export default class SaveRemotePlugin extends Plugin {
// console.log(local);
// console.log(localHistory);
new Notice("4/6 Starting to generate sync plan.");
new Notice("4/7 Checking password correct or not.");
this.syncStatus = "checking_password";
const passwordCheckResult = await isPasswordOk(
remoteRsp.Contents,
this.settings.password
);
if (!passwordCheckResult.ok) {
throw Error(passwordCheckResult.reason);
}
new Notice("5/7 Starting to generate sync plan.");
this.syncStatus = "generating_plan";
const syncPlan = await getSyncPlan(
remoteRsp.Contents,
@ -113,7 +123,7 @@ export default class SaveRemotePlugin extends Plugin {
// The operations above are read only and kind of safe.
// The operations below begins to write or delete (!!!) something.
new Notice("5/6 Save Remote Sync data exchanging!");
new Notice("6/7 Save Remote Sync data exchanging!");
this.syncStatus = "syncing";
await doActualSync(
@ -125,7 +135,7 @@ export default class SaveRemotePlugin extends Plugin {
this.settings.password
);
new Notice("6/6 Save Remote finish!");
new Notice("7/7 Save Remote finish!");
this.syncStatus = "finish";
this.syncStatus = "idle";
} catch (error) {
@ -133,7 +143,7 @@ export default class SaveRemotePlugin extends Plugin {
console.log(msg);
console.log(error);
new Notice(msg);
new Notice(error);
new Notice(error.message);
this.syncStatus = "idle";
}
});

View File

@ -17,13 +17,18 @@ import {
downloadFromRemote,
} from "./s3";
import { mkdirpInVault, SUPPORTED_SERVICES_TYPE, isHiddenPath } from "./misc";
import { decryptBase32ToString, encryptStringToBase32 } from "./encrypt";
import {
decryptBase32ToString,
encryptStringToBase32,
MAGIC_ENCRYPTED_PREFIX_BASE32,
} from "./encrypt";
export type SyncStatusType =
| "idle"
| "preparing"
| "getting_remote_meta"
| "getting_local_meta"
| "checking_password"
| "generating_plan"
| "syncing"
| "finish";
@ -61,6 +66,66 @@ export interface SyncPlanType {
mixedStates: Record<string, FileOrFolderMixedState>;
}
export interface PasswordCheckType {
ok: boolean;
reason:
| "ok"
| "empty_remote"
| "remote_encrypted_local_no_password"
| "password_matched"
| "password_not_matched"
| "remote_not_encrypted_local_has_password"
| "no_password_both_sides";
}
export const isPasswordOk = async (
remote: S3ObjectType[],
password: string = ""
) => {
if (remote === undefined || remote.length === 0) {
// remote empty
return {
ok: true,
reason: "empty_remote",
} as PasswordCheckType;
}
const santyCheckKey = remote[0].Key;
if (santyCheckKey.startsWith(MAGIC_ENCRYPTED_PREFIX_BASE32)) {
// this is encrypted!
// try to decrypt it using the provided password.
if (password === "") {
return {
ok: false,
reason: "remote_encrypted_local_no_password",
} as PasswordCheckType;
}
try {
const res = await decryptBase32ToString(santyCheckKey, password);
return {
ok: true,
reason: "password_matched",
} as PasswordCheckType;
} catch (error) {
return {
ok: false,
reason: "password_not_matched",
} as PasswordCheckType;
}
} else {
// it is not encrypted!
if (password !== "") {
return {
ok: false,
reason: "remote_not_encrypted_local_has_password",
} as PasswordCheckType;
}
return {
ok: true,
reason: "no_password_both_sides",
} as PasswordCheckType;
}
};
const ensembleMixedStates = async (
remote: S3ObjectType[],
local: TAbstractFile[],