fix encrypt method

This commit is contained in:
fyears 2024-03-27 00:02:01 +08:00
parent 62452341a3
commit 02e03681f7
4 changed files with 113 additions and 55 deletions

View File

@ -42,9 +42,18 @@ export class Cipher {
return content;
}
if (this.method === "openssl-base64") {
return await openssl.encryptArrayBuffer(content, this.password);
const res = await openssl.encryptArrayBuffer(content, this.password);
if (res === undefined) {
throw Error(`cannot encrypt content`);
}
return res;
} else if (this.method === "rclone-base64") {
return await this.cipherRClone!.encryptContentByCallingWorker(content);
const res =
await this.cipherRClone!.encryptContentByCallingWorker(content);
if (res === undefined) {
throw Error(`cannot encrypt content`);
}
return res;
} else {
throw Error(`not supported encrypt method=${this.method}`);
}
@ -56,9 +65,18 @@ export class Cipher {
return content;
}
if (this.method === "openssl-base64") {
return await openssl.decryptArrayBuffer(content, this.password);
const res = await openssl.decryptArrayBuffer(content, this.password);
if (res === undefined) {
throw Error(`cannot decrypt content`);
}
return res;
} else if (this.method === "rclone-base64") {
return await this.cipherRClone!.decryptContentByCallingWorker(content);
const res =
await this.cipherRClone!.decryptContentByCallingWorker(content);
if (res === undefined) {
throw Error(`cannot decrypt content`);
}
return res;
} else {
throw Error(`not supported decrypt method=${this.method}`);
}
@ -70,15 +88,23 @@ export class Cipher {
return name;
}
if (this.method === "openssl-base64") {
return await openssl.encryptStringToBase64url(name, this.password);
const res = await openssl.encryptStringToBase64url(name, this.password);
if (res === undefined) {
throw Error(`cannot encrypt name=${name}`);
}
return res;
} else if (this.method === "rclone-base64") {
return await this.cipherRClone!.encryptNameByCallingWorker(name);
const res = await this.cipherRClone!.encryptNameByCallingWorker(name);
if (res === undefined) {
throw Error(`cannot encrypt name=${name}`);
}
return res;
} else {
throw Error(`not supported encrypt method=${this.method}`);
}
}
async decryptName(name: string) {
async decryptName(name: string): Promise<string> {
// console.debug("start decryptName");
if (this.password === "") {
return name;
@ -88,7 +114,7 @@ export class Cipher {
// backward compitable with the openssl-base32
try {
const res = await openssl.decryptBase32ToString(name, this.password);
if (isVaildText(res)) {
if (res !== undefined && isVaildText(res)) {
return res;
} else {
throw Error(`cannot decrypt name=${name}`);
@ -102,7 +128,7 @@ export class Cipher {
name,
this.password
);
if (isVaildText(res)) {
if (res !== undefined && isVaildText(res)) {
return res;
} else {
throw Error(`cannot decrypt name=${name}`);
@ -110,9 +136,17 @@ export class Cipher {
} catch (error) {
throw Error(`cannot decrypt name=${name}`);
}
} else {
throw Error(
`method=${this.method} but the name=${name}, likely mismatch`
);
}
} else if (this.method === "rclone-base64") {
return await this.cipherRClone!.decryptNameByCallingWorker(name);
const res = await this.cipherRClone!.decryptNameByCallingWorker(name);
if (res === undefined) {
throw Error(`cannot decrypt name=${name}`);
}
return res;
} else {
throw Error(`not supported decrypt method=${this.method}`);
}
@ -136,7 +170,7 @@ export class Cipher {
* @param name
* @returns
*/
static isLikelyEncryptedName(name: string): boolean {
static isLikelyOpenSSLEncryptedName(name: string): boolean {
if (
name.startsWith(openssl.MAGIC_ENCRYPTED_PREFIX_BASE32) ||
name.startsWith(openssl.MAGIC_ENCRYPTED_PREFIX_BASE64URL)
@ -145,4 +179,37 @@ export class Cipher {
}
return false;
}
/**
* quick guess, no actual decryption here
* @param name
* @returns
*/
static isLikelyEncryptedName(name: string): boolean {
return Cipher.isLikelyOpenSSLEncryptedName(name);
}
/**
* quick guess, no actual decryption here, only openssl can be guessed here
* @param name
* @returns
*/
static isLikelyEncryptedNameNotMatchMethod(
name: string,
method: CipherMethodType
): boolean {
if (
Cipher.isLikelyOpenSSLEncryptedName(name) &&
method !== "openssl-base64"
) {
return true;
}
if (
!Cipher.isLikelyOpenSSLEncryptedName(name) &&
method === "openssl-base64"
) {
return true;
}
return false;
}
}

View File

@ -165,6 +165,9 @@ export const base64ToBase64url = (a: string, pad: boolean = false) => {
* @param a
*/
export const isVaildText = (a: string) => {
if (a === undefined) {
return false;
}
// If the regex matches, the string is invalid.
return !XRegExp("\\p{Cc}|\\p{Cf}|\\p{Co}|\\p{Cn}|\\p{Zl}|\\p{Zp}", "A").test(
a

View File

@ -125,15 +125,9 @@ class PasswordModal extends Modal {
class EncryptionMethodModal extends Modal {
plugin: RemotelySavePlugin;
newEncryptionMethod: CipherMethodType;
constructor(
app: App,
plugin: RemotelySavePlugin,
newEncryptionMethod: CipherMethodType
) {
constructor(app: App, plugin: RemotelySavePlugin) {
super(app);
this.plugin = plugin;
this.newEncryptionMethod = newEncryptionMethod;
}
onOpen() {
@ -153,22 +147,13 @@ class EncryptionMethodModal extends Modal {
});
});
new Setting(contentEl)
.addButton((button) => {
button.setButtonText(t("confirm"));
button.onClick(async () => {
this.plugin.settings.encryptionMethod = this.newEncryptionMethod;
await this.plugin.saveSettings();
this.close();
});
button.setClass("encryptionmethod-second-confirm");
})
.addButton((button) => {
button.setButtonText(t("goback"));
button.onClick(() => {
this.close();
});
new Setting(contentEl).addButton((button) => {
button.setButtonText(t("confirm"));
button.onClick(async () => {
this.close();
});
button.setClass("encryptionmethod-second-confirm");
});
}
onClose() {
@ -1693,26 +1678,17 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
.setName(t("settings_encryptionmethod"))
.setDesc(stringToFragment(t("settings_encryptionmethod_desc")))
.addDropdown((dropdown) => {
dropdown.addOption(
"rclone-base64",
t("settings_encryptionmethod_rclone")
);
dropdown.addOption(
"openssl-base64",
t("settings_encryptionmethod_openssl")
);
dropdown.onChange(async (val: string) => {
if (this.plugin.settings.password === "") {
dropdown
.addOption("rclone-base64", t("settings_encryptionmethod_rclone"))
.addOption("openssl-base64", t("settings_encryptionmethod_openssl"))
.setValue(this.plugin.settings.encryptionMethod ?? "rclone-base64")
.onChange(async (val: string) => {
this.plugin.settings.encryptionMethod = val as CipherMethodType;
await this.plugin.saveSettings();
} else {
new EncryptionMethodModal(
this.app,
this.plugin,
val as CipherMethodType
).open();
}
});
if (this.plugin.settings.password !== "") {
new EncryptionMethodModal(this.app, this.plugin).open();
}
});
});
new Setting(basicDiv)

View File

@ -53,8 +53,9 @@ export interface PasswordCheckType {
| "unknown_encryption_method"
| "remote_encrypted_local_no_password"
| "password_matched"
| "password_not_matched_or_remote_not_encrypted"
| "likely_no_password_both_sides";
| "password_or_method_not_matched_or_remote_not_encrypted"
| "likely_no_password_both_sides"
| "encryption_method_not_matched";
}
export const isPasswordOk = async (
@ -91,8 +92,19 @@ export const isPasswordOk = async (
reason: "unknown_encryption_method",
};
}
if (
Cipher.isLikelyEncryptedNameNotMatchMethod(santyCheckKey, cipher.method)
) {
return {
ok: false,
reason: "encryption_method_not_matched",
};
}
try {
await cipher.decryptName(santyCheckKey);
const k = await cipher.decryptName(santyCheckKey);
if (k === undefined) {
throw Error(`decryption failed`);
}
return {
ok: true,
reason: "password_matched",
@ -100,7 +112,7 @@ export const isPasswordOk = async (
} catch (error) {
return {
ok: false,
reason: "password_not_matched_or_remote_not_encrypted",
reason: "password_or_method_not_matched_or_remote_not_encrypted",
};
}
}