mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
crypto: remove crypto-worker & simplify crypto interface
This commit is contained in:
committed by
Abdullah Atta
parent
6554f900d7
commit
fac788d2a9
1426
apps/web/package-lock.json
generated
1426
apps/web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,6 @@
|
|||||||
"@notesnook/common": "file:../../packages/common",
|
"@notesnook/common": "file:../../packages/common",
|
||||||
"@notesnook/core": "file:../../packages/core",
|
"@notesnook/core": "file:../../packages/core",
|
||||||
"@notesnook/crypto": "file:../../packages/crypto",
|
"@notesnook/crypto": "file:../../packages/crypto",
|
||||||
"@notesnook/crypto-worker": "file:../../packages/crypto-worker",
|
|
||||||
"@notesnook/desktop": "file:../desktop",
|
"@notesnook/desktop": "file:../desktop",
|
||||||
"@notesnook/editor": "file:../../packages/editor",
|
"@notesnook/editor": "file:../../packages/editor",
|
||||||
"@notesnook/logger": "file:../../packages/logger",
|
"@notesnook/logger": "file:../../packages/logger",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { xxhash64, createXXHash64 } from "hash-wasm";
|
|||||||
import axios, { AxiosProgressEvent } from "axios";
|
import axios, { AxiosProgressEvent } from "axios";
|
||||||
import { AppEventManager, AppEvents } from "../common/app-events";
|
import { AppEventManager, AppEvents } from "../common/app-events";
|
||||||
import { StreamableFS } from "@notesnook/streamable-fs";
|
import { StreamableFS } from "@notesnook/streamable-fs";
|
||||||
import { getNNCrypto } from "./nncrypto.stub";
|
import { NNCrypto } from "./nncrypto";
|
||||||
import hosts from "@notesnook/core/dist/utils/constants";
|
import hosts from "@notesnook/core/dist/utils/constants";
|
||||||
import { sendAttachmentsProgressEvent } from "@notesnook/core/dist/common";
|
import { sendAttachmentsProgressEvent } from "@notesnook/core/dist/common";
|
||||||
import { saveAs } from "file-saver";
|
import { saveAs } from "file-saver";
|
||||||
@@ -34,7 +34,7 @@ import { ProgressStream } from "../utils/streams/progress-stream";
|
|||||||
import { consumeReadableStream } from "../utils/stream";
|
import { consumeReadableStream } from "../utils/stream";
|
||||||
import { Base64DecoderStream } from "../utils/streams/base64-decoder-stream";
|
import { Base64DecoderStream } from "../utils/streams/base64-decoder-stream";
|
||||||
import { toBlob } from "@notesnook-importer/core/dist/src/utils/stream";
|
import { toBlob } from "@notesnook-importer/core/dist/src/utils/stream";
|
||||||
import { Cipher, OutputFormat, SerializedKey } from "@notesnook/crypto";
|
import { Cipher, DataFormat, SerializedKey } from "@notesnook/crypto";
|
||||||
import { IDataType } from "hash-wasm/dist/lib/util";
|
import { IDataType } from "hash-wasm/dist/lib/util";
|
||||||
import { IndexedDBKVStore } from "./key-value";
|
import { IndexedDBKVStore } from "./key-value";
|
||||||
import FileHandle from "@notesnook/streamable-fs/dist/src/filehandle";
|
import FileHandle from "@notesnook/streamable-fs/dist/src/filehandle";
|
||||||
@@ -53,8 +53,6 @@ async function writeEncryptedFile(
|
|||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
hash: string
|
hash: string
|
||||||
) {
|
) {
|
||||||
const crypto = await getNNCrypto();
|
|
||||||
|
|
||||||
if (!IndexedDBKVStore.isIndexedDBSupported())
|
if (!IndexedDBKVStore.isIndexedDBSupported())
|
||||||
throw new Error("This browser does not support IndexedDB.");
|
throw new Error("This browser does not support IndexedDB.");
|
||||||
|
|
||||||
@@ -65,7 +63,7 @@ async function writeEncryptedFile(
|
|||||||
const fileHandle = await streamablefs.createFile(hash, file.size, file.type);
|
const fileHandle = await streamablefs.createFile(hash, file.size, file.type);
|
||||||
sendAttachmentsProgressEvent("encrypt", hash, 1, 0);
|
sendAttachmentsProgressEvent("encrypt", hash, 1, 0);
|
||||||
|
|
||||||
const { iv, stream } = await crypto.createEncryptionStream(key);
|
const { iv, stream } = await NNCrypto.createEncryptionStream(key);
|
||||||
await file
|
await file
|
||||||
.stream()
|
.stream()
|
||||||
.pipeThrough(new ChunkedStream(CHUNK_SIZE))
|
.pipeThrough(new ChunkedStream(CHUNK_SIZE))
|
||||||
@@ -84,7 +82,7 @@ async function writeEncryptedFile(
|
|||||||
)
|
)
|
||||||
.pipeTo(fileHandle.writeable);
|
.pipeTo(fileHandle.writeable);
|
||||||
|
|
||||||
sendAttachmentsProgressEvent("encrypt", hash, 1);
|
sendAttachmentsProgressEvent("encrypt", hash, 1, 1);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
chunkSize: CHUNK_SIZE,
|
chunkSize: CHUNK_SIZE,
|
||||||
@@ -155,15 +153,14 @@ async function hashStream(reader: ReadableStreamDefaultReader<Uint8Array>) {
|
|||||||
async function readEncrypted(
|
async function readEncrypted(
|
||||||
filename: string,
|
filename: string,
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
cipherData: Cipher & { outputType: OutputFormat }
|
cipherData: Cipher<DataFormat> & { outputType: DataFormat }
|
||||||
) {
|
) {
|
||||||
const fileHandle = await streamablefs.readFile(filename);
|
const fileHandle = await streamablefs.readFile(filename);
|
||||||
if (!fileHandle) {
|
if (!fileHandle) {
|
||||||
console.error(`File not found. (File hash: ${filename})`);
|
console.error(`File not found. (File hash: ${filename})`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const crypto = await getNNCrypto();
|
const decryptionStream = await NNCrypto.createDecryptionStream(
|
||||||
const decryptionStream = await crypto.createDecryptionStream(
|
|
||||||
key,
|
key,
|
||||||
cipherData.iv
|
cipherData.iv
|
||||||
);
|
);
|
||||||
@@ -527,8 +524,7 @@ export async function decryptFile(
|
|||||||
|
|
||||||
const { key, iv } = fileMetadata;
|
const { key, iv } = fileMetadata;
|
||||||
|
|
||||||
const crypto = await getNNCrypto();
|
const decryptionStream = await NNCrypto.createDecryptionStream(key, iv);
|
||||||
const decryptionStream = await crypto.createDecryptionStream(key, iv);
|
|
||||||
return await toBlob(fileHandle.readable.pipeThrough(decryptionStream));
|
return await toBlob(fileHandle.readable.pipeThrough(decryptionStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of the Notesnook project (https://notesnook.com/)
|
|
||||||
|
|
||||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { INNCrypto } from "@notesnook/crypto/dist/src/interfaces";
|
|
||||||
import CryptoWorker from "@notesnook/crypto-worker/dist/src/worker.js?worker";
|
|
||||||
|
|
||||||
async function loadNNCrypto() {
|
|
||||||
const hasWorker = "Worker" in window || "Worker" in global;
|
|
||||||
// if (IS_DESKTOP_APP && window.NativeNNCrypto) {
|
|
||||||
// return window.NativeNNCrypto;
|
|
||||||
// } else
|
|
||||||
if (hasWorker) {
|
|
||||||
const { NNCryptoWorker } = await import("@notesnook/crypto-worker");
|
|
||||||
return NNCryptoWorker;
|
|
||||||
} else {
|
|
||||||
const { NNCrypto } = await import("@notesnook/crypto");
|
|
||||||
return NNCrypto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let instance: INNCrypto | null = null;
|
|
||||||
|
|
||||||
export function getNNCrypto(): Promise<INNCrypto> {
|
|
||||||
if (instance) return Promise.resolve(instance);
|
|
||||||
return queueify<INNCrypto>(async () => {
|
|
||||||
const NNCrypto = await loadNNCrypto();
|
|
||||||
instance = new NNCrypto(new CryptoWorker());
|
|
||||||
return instance;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let processing = false;
|
|
||||||
type PromiseResolve = <T>(value: Awaited<T>) => void;
|
|
||||||
const queue: Array<PromiseResolve> = [];
|
|
||||||
async function queueify<T>(action: () => Promise<T>): Promise<T> {
|
|
||||||
if (processing)
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
queue.push(resolve as PromiseResolve);
|
|
||||||
});
|
|
||||||
|
|
||||||
processing = true;
|
|
||||||
const result = await action();
|
|
||||||
processing = false;
|
|
||||||
|
|
||||||
while (queue.length > 0) {
|
|
||||||
const resolve = queue.pop();
|
|
||||||
if (!resolve) continue;
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
24
apps/web/src/interfaces/nncrypto.ts
Normal file
24
apps/web/src/interfaces/nncrypto.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the Notesnook project (https://notesnook.com/)
|
||||||
|
|
||||||
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { INNCrypto } from "@notesnook/crypto";
|
||||||
|
import CryptoWorker from "./crypto.worker?worker";
|
||||||
|
import { wrap } from "comlink";
|
||||||
|
|
||||||
|
export const NNCrypto = wrap<INNCrypto>(new CryptoWorker()) as INNCrypto;
|
||||||
40
apps/web/src/interfaces/nncrypto.worker.ts
Normal file
40
apps/web/src/interfaces/nncrypto.worker.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the Notesnook project (https://notesnook.com/)
|
||||||
|
|
||||||
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NNCrypto, Chunk, SerializedKey } from "@notesnook/crypto";
|
||||||
|
import { expose, transfer } from "comlink";
|
||||||
|
|
||||||
|
class NNCryptoWorker extends NNCrypto {
|
||||||
|
override async createDecryptionStream(
|
||||||
|
key: SerializedKey,
|
||||||
|
iv: string
|
||||||
|
): Promise<TransformStream<Uint8Array, Uint8Array>> {
|
||||||
|
const stream = await super.createDecryptionStream(key, iv);
|
||||||
|
return transfer(stream, [stream]);
|
||||||
|
}
|
||||||
|
|
||||||
|
override async createEncryptionStream(
|
||||||
|
key: SerializedKey
|
||||||
|
): Promise<{ iv: string; stream: TransformStream<Chunk, Uint8Array> }> {
|
||||||
|
const result = await super.createEncryptionStream(key);
|
||||||
|
return transfer(result, [result.stream]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expose(new NNCryptoWorker());
|
||||||
@@ -23,7 +23,7 @@ import {
|
|||||||
MemoryKVStore,
|
MemoryKVStore,
|
||||||
IKVStore
|
IKVStore
|
||||||
} from "./key-value";
|
} from "./key-value";
|
||||||
import { getNNCrypto } from "./nncrypto.stub";
|
import { NNCrypto } from "./nncrypto";
|
||||||
import type { Cipher, SerializedKey } from "@notesnook/crypto/dist/src/types";
|
import type { Cipher, SerializedKey } from "@notesnook/crypto/dist/src/types";
|
||||||
|
|
||||||
type EncryptedKey = { iv: Uint8Array; cipher: BufferSource };
|
type EncryptedKey = { iv: Uint8Array; cipher: BufferSource };
|
||||||
@@ -82,8 +82,7 @@ export class NNStorage {
|
|||||||
const { password, salt } = credentials;
|
const { password, salt } = credentials;
|
||||||
if (!password) throw new Error("Invalid data provided to deriveCryptoKey.");
|
if (!password) throw new Error("Invalid data provided to deriveCryptoKey.");
|
||||||
|
|
||||||
const crypto = await getNNCrypto();
|
const keyData = await NNCrypto.exportKey(password, salt);
|
||||||
const keyData = await crypto.exportKey(password, salt);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(await IndexedDBKVStore.isIndexedDBSupported()) &&
|
(await IndexedDBKVStore.isIndexedDBSupported()) &&
|
||||||
@@ -124,41 +123,39 @@ export class NNStorage {
|
|||||||
): Promise<SerializedKey> {
|
): Promise<SerializedKey> {
|
||||||
if (!password)
|
if (!password)
|
||||||
throw new Error("Invalid data provided to generateCryptoKey.");
|
throw new Error("Invalid data provided to generateCryptoKey.");
|
||||||
const crypto = await getNNCrypto();
|
|
||||||
return await crypto.exportKey(password, salt);
|
return await NNCrypto.exportKey(password, salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
async hash(password: string, email: string): Promise<string> {
|
async hash(password: string, email: string): Promise<string> {
|
||||||
const crypto = await getNNCrypto();
|
return await NNCrypto.hash(password, `${APP_SALT}${email}`);
|
||||||
return await crypto.hash(password, `${APP_SALT}${email}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async encrypt(key: SerializedKey, plainText: string): Promise<Cipher> {
|
encrypt(key: SerializedKey, plainText: string): Promise<Cipher<"base64">> {
|
||||||
const crypto = await getNNCrypto();
|
return NNCrypto.encrypt(key, plainText, "text", "base64");
|
||||||
return await crypto.encrypt(
|
|
||||||
key,
|
|
||||||
{ format: "text", data: plainText },
|
|
||||||
"base64"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async decrypt(
|
encryptMulti(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
cipherData: Cipher
|
items: string[]
|
||||||
|
): Promise<Cipher<"base64">[]> {
|
||||||
|
return NNCrypto.encryptMulti(key, items, "text", "base64");
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypt(
|
||||||
|
key: SerializedKey,
|
||||||
|
cipherData: Cipher<"base64">
|
||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
const crypto = await getNNCrypto();
|
|
||||||
cipherData.format = "base64";
|
cipherData.format = "base64";
|
||||||
return await crypto.decrypt(key, cipherData, "text");
|
return NNCrypto.decrypt(key, cipherData, "text");
|
||||||
}
|
}
|
||||||
|
|
||||||
async decryptMulti(
|
decryptMulti(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
items: Cipher[]
|
items: Cipher<"base64">[]
|
||||||
): Promise<string[] | undefined> {
|
): Promise<string[] | undefined> {
|
||||||
const crypto = await getNNCrypto();
|
|
||||||
|
|
||||||
items.forEach((c) => (c.format = "base64"));
|
items.forEach((c) => (c.format = "base64"));
|
||||||
return await crypto.decryptMulti(key, items, "text");
|
return NNCrypto.decryptMulti(key, items, "text");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,23 +223,3 @@ async function aesDecrypt(
|
|||||||
);
|
);
|
||||||
return dec.decode(plainText);
|
return dec.decode(plainText);
|
||||||
}
|
}
|
||||||
|
|
||||||
// async function main() {
|
|
||||||
// const nncrypto = await getNNCrypto();
|
|
||||||
// const electronNNCrypto = new NNCryptoElectron();
|
|
||||||
|
|
||||||
// console.time("nncrypto");
|
|
||||||
// for (let i = 0; i < 100; ++i) {
|
|
||||||
// await nncrypto.hash("mypassword", APP_SALT);
|
|
||||||
// }
|
|
||||||
// console.timeEnd("nncrypto");
|
|
||||||
|
|
||||||
// console.time("electron");
|
|
||||||
// for (let i = 0; i < 100; ++i) {
|
|
||||||
// await electronNNCrypto.hash("mypassword", APP_SALT);
|
|
||||||
// }
|
|
||||||
// console.timeEnd("electron");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// main();
|
|
||||||
// setTimeout(main, 10000);
|
|
||||||
|
|||||||
@@ -1,191 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of the Notesnook project (https://notesnook.com/)
|
|
||||||
|
|
||||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
|
||||||
SerializedKey,
|
|
||||||
Plaintext,
|
|
||||||
OutputFormat,
|
|
||||||
Cipher,
|
|
||||||
EncryptionKey,
|
|
||||||
INNCrypto,
|
|
||||||
Output
|
|
||||||
} from "@notesnook/crypto";
|
|
||||||
import { NNCryptoWorkerModule } from "./src/worker";
|
|
||||||
import { wrap } from "comlink";
|
|
||||||
|
|
||||||
export class NNCryptoWorker implements INNCrypto {
|
|
||||||
private workermodule?: NNCryptoWorkerModule;
|
|
||||||
private isReady = false;
|
|
||||||
|
|
||||||
constructor(private readonly worker?: Worker) {}
|
|
||||||
|
|
||||||
private async init() {
|
|
||||||
if (!this.worker) throw new Error("worker cannot be undefined.");
|
|
||||||
if (this.isReady) return;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
this.workermodule = wrap<NNCryptoWorkerModule>(this.worker);
|
|
||||||
// this.workermodule = await spawn<NNCryptoWorkerModule>(this.worker);
|
|
||||||
this.isReady = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async encrypt(
|
|
||||||
key: SerializedKey,
|
|
||||||
plaintext: Plaintext<OutputFormat>,
|
|
||||||
outputFormat: OutputFormat = "uint8array"
|
|
||||||
): Promise<Cipher> {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
|
|
||||||
return this.workermodule.encrypt(key, plaintext, outputFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
async decrypt<TOutputFormat extends OutputFormat>(
|
|
||||||
key: SerializedKey,
|
|
||||||
cipherData: Cipher,
|
|
||||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
|
||||||
): Promise<Output<TOutputFormat>> {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
|
|
||||||
return this.workermodule.decrypt(key, cipherData, outputFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
async decryptMulti<TOutputFormat extends OutputFormat>(
|
|
||||||
key: SerializedKey,
|
|
||||||
items: Cipher[],
|
|
||||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
|
||||||
): Promise<Output<TOutputFormat>[]> {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
|
|
||||||
return this.workermodule.decryptMulti(key, items, outputFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
async hash(password: string, salt: string): Promise<string> {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
|
|
||||||
return this.workermodule.hash(password, salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
async deriveKey(password: string, salt?: string): Promise<EncryptionKey> {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
|
|
||||||
return this.workermodule.deriveKey(password, salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
async exportKey(password: string, salt?: string): Promise<SerializedKey> {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
|
|
||||||
return this.workermodule.exportKey(password, salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
async createEncryptionStream(key: SerializedKey) {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
return this.workermodule.createEncryptionStream(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
async createDecryptionStream(key: SerializedKey, iv: string) {
|
|
||||||
await this.init();
|
|
||||||
if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
const { stream } = await this.workermodule.createDecryptionStream(key, iv);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
// async encryptStream(
|
|
||||||
// key: SerializedKey,
|
|
||||||
// stream: IStreamable,
|
|
||||||
// streamId?: string
|
|
||||||
// ): Promise<string> {
|
|
||||||
// if (!streamId) throw new Error("streamId is required.");
|
|
||||||
// await this.init();
|
|
||||||
// if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
// if (!this.worker) throw new Error("Worker is not ready.");
|
|
||||||
|
|
||||||
// const eventListener = await this.createWorkerStream(
|
|
||||||
// streamId,
|
|
||||||
// stream,
|
|
||||||
// () => {
|
|
||||||
// if (this.worker)
|
|
||||||
// this.worker.removeEventListener("message", eventListener);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// this.worker.addEventListener("message", eventListener);
|
|
||||||
// const iv = await this.workermodule.createEncryptionStream(streamId, key);
|
|
||||||
// this.worker.removeEventListener("message", eventListener);
|
|
||||||
// return iv;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async decryptStream(
|
|
||||||
// key: SerializedKey,
|
|
||||||
// iv: string,
|
|
||||||
// stream: IStreamable,
|
|
||||||
// streamId?: string
|
|
||||||
// ): Promise<void> {
|
|
||||||
// if (!streamId) throw new Error("streamId is required.");
|
|
||||||
// await this.init();
|
|
||||||
// if (!this.workermodule) throw new Error("Worker module is not ready.");
|
|
||||||
// if (!this.worker) throw new Error("Worker is not ready.");
|
|
||||||
|
|
||||||
// const eventListener = await this.createWorkerStream(
|
|
||||||
// streamId,
|
|
||||||
// stream,
|
|
||||||
// () => {
|
|
||||||
// if (this.worker)
|
|
||||||
// this.worker.removeEventListener("message", eventListener);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// this.worker.addEventListener("message", eventListener);
|
|
||||||
// await this.workermodule.createDecryptionStream(streamId, iv, key);
|
|
||||||
// this.worker.removeEventListener("message", eventListener);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private async createWorkerStream(
|
|
||||||
// streamId: string,
|
|
||||||
// stream: IStreamable,
|
|
||||||
// done: () => void
|
|
||||||
// ): Promise<EventListenerObject> {
|
|
||||||
// const readEventType = `${streamId}:read`;
|
|
||||||
// const writeEventType = `${streamId}:write`;
|
|
||||||
// let finished = false;
|
|
||||||
// return {
|
|
||||||
// handleEvent: async (ev: MessageEvent) => {
|
|
||||||
// if (finished) return;
|
|
||||||
|
|
||||||
// const { type } = ev.data;
|
|
||||||
// if (type === readEventType) {
|
|
||||||
// const chunk = await stream.read();
|
|
||||||
// if (!chunk || !this.worker || !chunk.data) return;
|
|
||||||
// this.worker.postMessage({ type, data: chunk }, [chunk.data.buffer]);
|
|
||||||
// } else if (type === writeEventType) {
|
|
||||||
// const chunk = ev.data.data as Chunk;
|
|
||||||
// await stream.write(chunk);
|
|
||||||
// if (chunk.final) {
|
|
||||||
// finished = true;
|
|
||||||
// done();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
49
packages/crypto-worker/package-lock.json
generated
49
packages/crypto-worker/package-lock.json
generated
@@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@notesnook/crypto-worker",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"lockfileVersion": 2,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "@notesnook/crypto-worker",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"license": "GPL-3.0-or-later",
|
|
||||||
"dependencies": {
|
|
||||||
"@notesnook/crypto": "file:../crypto",
|
|
||||||
"comlink": "^4.3.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {}
|
|
||||||
},
|
|
||||||
"../crypto": {
|
|
||||||
"name": "@notesnook/crypto",
|
|
||||||
"version": "1.1.1",
|
|
||||||
"license": "GPL-3.0-or-later",
|
|
||||||
"dependencies": {
|
|
||||||
"@notesnook/sodium": "file:../sodium"
|
|
||||||
},
|
|
||||||
"devDependencies": {}
|
|
||||||
},
|
|
||||||
"node_modules/@notesnook/crypto": {
|
|
||||||
"resolved": "../crypto",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/comlink": {
|
|
||||||
"version": "4.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/comlink/-/comlink-4.3.1.tgz",
|
|
||||||
"integrity": "sha512-+YbhUdNrpBZggBAHWcgQMLPLH1KDF3wJpeqrCKieWQ8RL7atmgsgTQko1XEBK6PsecfopWNntopJ+ByYG1lRaA=="
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@notesnook/crypto": {
|
|
||||||
"version": "file:../crypto",
|
|
||||||
"requires": {
|
|
||||||
"@notesnook/sodium": "file:../sodium"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"comlink": {
|
|
||||||
"version": "4.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/comlink/-/comlink-4.3.1.tgz",
|
|
||||||
"integrity": "sha512-+YbhUdNrpBZggBAHWcgQMLPLH1KDF3wJpeqrCKieWQ8RL7atmgsgTQko1XEBK6PsecfopWNntopJ+ByYG1lRaA=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@notesnook/crypto-worker",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "./dist/index.js",
|
|
||||||
"types": "./dist/index.d.ts",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc --declaration --outDir ./dist"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "GPL-3.0-or-later",
|
|
||||||
"dependencies": {
|
|
||||||
"@notesnook/crypto": "file:../crypto",
|
|
||||||
"comlink": "^4.3.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of the Notesnook project (https://notesnook.com/)
|
|
||||||
|
|
||||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
|
||||||
Cipher,
|
|
||||||
OutputFormat,
|
|
||||||
Plaintext,
|
|
||||||
SerializedKey
|
|
||||||
} from "@notesnook/crypto/dist/src/types";
|
|
||||||
import { expose, transfer } from "comlink";
|
|
||||||
import type { Decryption, NNCrypto, Output } from "@notesnook/crypto";
|
|
||||||
|
|
||||||
let crypto: NNCrypto | null = null;
|
|
||||||
let decryption: typeof Decryption | null = null;
|
|
||||||
|
|
||||||
async function loadNNCrypto(): Promise<NNCrypto> {
|
|
||||||
if (crypto) return crypto;
|
|
||||||
const { NNCrypto } = await import("@notesnook/crypto");
|
|
||||||
return (crypto = new NNCrypto());
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadDecryptionModule(): Promise<typeof Decryption> {
|
|
||||||
if (decryption) return decryption;
|
|
||||||
const { Decryption } = await import("@notesnook/crypto");
|
|
||||||
return (decryption = Decryption);
|
|
||||||
}
|
|
||||||
|
|
||||||
const module = {
|
|
||||||
exportKey: async function (password: string, salt?: string) {
|
|
||||||
const crypto = await loadNNCrypto();
|
|
||||||
return crypto.exportKey(password, salt);
|
|
||||||
},
|
|
||||||
deriveKey: async function (password: string, salt?: string) {
|
|
||||||
const crypto = await loadNNCrypto();
|
|
||||||
return crypto.deriveKey(password, salt);
|
|
||||||
},
|
|
||||||
hash: async function (password: string, salt: string) {
|
|
||||||
const crypto = await loadNNCrypto();
|
|
||||||
return crypto.hash(password, salt);
|
|
||||||
},
|
|
||||||
encrypt: async function (
|
|
||||||
key: SerializedKey,
|
|
||||||
plaintext: Plaintext<OutputFormat>,
|
|
||||||
outputFormat?: OutputFormat
|
|
||||||
) {
|
|
||||||
const crypto = await loadNNCrypto();
|
|
||||||
return crypto.encrypt(key, plaintext, outputFormat);
|
|
||||||
},
|
|
||||||
decrypt: async function <TOutputFormat extends OutputFormat>(
|
|
||||||
key: SerializedKey,
|
|
||||||
cipherData: Cipher,
|
|
||||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
|
||||||
) {
|
|
||||||
const decryption = await loadDecryptionModule();
|
|
||||||
return decryption.decrypt(key, cipherData, outputFormat);
|
|
||||||
},
|
|
||||||
decryptMulti: async function <TOutputFormat extends OutputFormat>(
|
|
||||||
key: SerializedKey,
|
|
||||||
items: Cipher[],
|
|
||||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
|
||||||
) {
|
|
||||||
const decryption = await loadDecryptionModule();
|
|
||||||
const decryptedItems: Output<TOutputFormat>[] = [];
|
|
||||||
for (const cipherData of items) {
|
|
||||||
decryptedItems.push(decryption.decrypt(key, cipherData, outputFormat));
|
|
||||||
}
|
|
||||||
return decryptedItems;
|
|
||||||
},
|
|
||||||
createEncryptionStream: async function (key: SerializedKey) {
|
|
||||||
const crypto = await loadNNCrypto();
|
|
||||||
const stream = await crypto.createEncryptionStream(key);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
return transfer(stream, [stream.stream]);
|
|
||||||
},
|
|
||||||
createDecryptionStream: async function (key: SerializedKey, iv: string) {
|
|
||||||
const crypto = await loadNNCrypto();
|
|
||||||
const obj = { stream: await crypto.createDecryptionStream(key, iv) };
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
return transfer(obj, [obj.stream]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export type NNCryptoWorkerModule = typeof module;
|
|
||||||
|
|
||||||
expose(module);
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig",
|
|
||||||
"compilerOptions": {
|
|
||||||
"lib": ["DOM", "WebWorker", "ES2015"],
|
|
||||||
"outDir": "./dist"
|
|
||||||
},
|
|
||||||
"include": ["./index.ts", "./src/"]
|
|
||||||
}
|
|
||||||
@@ -26,9 +26,9 @@ import Password from "./src/password";
|
|||||||
import {
|
import {
|
||||||
Cipher,
|
Cipher,
|
||||||
EncryptionKey,
|
EncryptionKey,
|
||||||
|
Input,
|
||||||
Output,
|
Output,
|
||||||
OutputFormat,
|
DataFormat,
|
||||||
Plaintext,
|
|
||||||
SerializedKey
|
SerializedKey
|
||||||
} from "./src/types";
|
} from "./src/types";
|
||||||
|
|
||||||
@@ -41,27 +41,45 @@ export class NNCrypto implements INNCrypto {
|
|||||||
this.isReady = true;
|
this.isReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async encrypt<TFormat extends OutputFormat>(
|
async encrypt<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
plaintext: Plaintext<TFormat>,
|
input: Input<DataFormat>,
|
||||||
outputFormat: OutputFormat = "uint8array"
|
format: DataFormat,
|
||||||
): Promise<Cipher> {
|
outputFormat: TOutputFormat = "uint8array" as TOutputFormat
|
||||||
|
): Promise<Cipher<TOutputFormat>> {
|
||||||
await this.init();
|
await this.init();
|
||||||
return Encryption.encrypt(key, plaintext, outputFormat);
|
return Encryption.encrypt(
|
||||||
|
key,
|
||||||
|
input,
|
||||||
|
format,
|
||||||
|
outputFormat
|
||||||
|
) as Cipher<TOutputFormat>;
|
||||||
}
|
}
|
||||||
|
|
||||||
async decrypt<TOutputFormat extends OutputFormat>(
|
async encryptMulti<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
cipherData: Cipher,
|
items: Input<DataFormat>[],
|
||||||
|
format: DataFormat,
|
||||||
|
outputFormat = "uint8array" as TOutputFormat
|
||||||
|
): Promise<Cipher<TOutputFormat>[]> {
|
||||||
|
await this.init();
|
||||||
|
return items.map((data) =>
|
||||||
|
Encryption.encrypt(key, data, format, outputFormat)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async decrypt<TOutputFormat extends DataFormat>(
|
||||||
|
key: SerializedKey,
|
||||||
|
cipherData: Cipher<DataFormat>,
|
||||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
outputFormat: TOutputFormat = "text" as TOutputFormat
|
||||||
): Promise<Output<TOutputFormat>> {
|
): Promise<Output<TOutputFormat>> {
|
||||||
await this.init();
|
await this.init();
|
||||||
return Decryption.decrypt(key, cipherData, outputFormat);
|
return Decryption.decrypt(key, cipherData, outputFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
async decryptMulti<TOutputFormat extends OutputFormat>(
|
async decryptMulti<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
items: Cipher[],
|
items: Cipher<DataFormat>[],
|
||||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
outputFormat: TOutputFormat = "text" as TOutputFormat
|
||||||
): Promise<Output<TOutputFormat>[]> {
|
): Promise<Output<TOutputFormat>[]> {
|
||||||
await this.init();
|
await this.init();
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ import {
|
|||||||
from_hex
|
from_hex
|
||||||
} from "@notesnook/sodium";
|
} from "@notesnook/sodium";
|
||||||
import KeyUtils from "./keyutils";
|
import KeyUtils from "./keyutils";
|
||||||
import { Cipher, Output, OutputFormat, SerializedKey } from "./types";
|
import { Cipher, Output, DataFormat, SerializedKey } from "./types";
|
||||||
|
|
||||||
export default class Decryption {
|
export default class Decryption {
|
||||||
private static transformInput(cipherData: Cipher): Uint8Array {
|
private static transformInput(cipherData: Cipher<DataFormat>): Uint8Array {
|
||||||
let input: Uint8Array | null = null;
|
let input: Uint8Array | null = null;
|
||||||
if (
|
if (
|
||||||
typeof cipherData.cipher === "string" &&
|
typeof cipherData.cipher === "string" &&
|
||||||
@@ -54,9 +54,9 @@ export default class Decryption {
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
static decrypt<TOutputFormat extends OutputFormat>(
|
static decrypt<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
cipherData: Cipher,
|
cipherData: Cipher<DataFormat>,
|
||||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
outputFormat: TOutputFormat = "text" as TOutputFormat
|
||||||
): Output<TOutputFormat> {
|
): Output<TOutputFormat> {
|
||||||
if (!key.salt && cipherData.salt) key.salt = cipherData.salt;
|
if (!key.salt && cipherData.salt) key.salt = cipherData.salt;
|
||||||
|
|||||||
@@ -30,32 +30,34 @@ import {
|
|||||||
base64_variants
|
base64_variants
|
||||||
} from "@notesnook/sodium";
|
} from "@notesnook/sodium";
|
||||||
import KeyUtils from "./keyutils";
|
import KeyUtils from "./keyutils";
|
||||||
import { Chunk, Cipher, OutputFormat, Plaintext, SerializedKey } from "./types";
|
import { Chunk, Cipher, Input, DataFormat, SerializedKey } from "./types";
|
||||||
|
|
||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
export default class Encryption {
|
export default class Encryption {
|
||||||
private static transformInput(
|
private static transformInput(
|
||||||
plaintext: Plaintext<OutputFormat>
|
input: Input<DataFormat>,
|
||||||
|
format: DataFormat
|
||||||
): Uint8Array {
|
): Uint8Array {
|
||||||
let data: Uint8Array | null = null;
|
let data: Uint8Array | null = null;
|
||||||
if (typeof plaintext.data === "string" && plaintext.format === "base64") {
|
if (typeof input === "string" && format === "base64") {
|
||||||
data = from_base64(plaintext.data, base64_variants.ORIGINAL);
|
data = from_base64(input, base64_variants.ORIGINAL);
|
||||||
} else if (typeof plaintext.data === "string") {
|
} else if (typeof input === "string") {
|
||||||
data = encoder.encode(plaintext.data);
|
data = encoder.encode(input);
|
||||||
} else if (plaintext.data instanceof Uint8Array) {
|
} else if (input instanceof Uint8Array) {
|
||||||
data = plaintext.data;
|
data = input;
|
||||||
}
|
}
|
||||||
if (!data) throw new Error("Data cannot be null.");
|
if (!data) throw new Error("Data cannot be null.");
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static encrypt(
|
static encrypt<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
plaintext: Plaintext<OutputFormat>,
|
input: Input<DataFormat>,
|
||||||
outputFormat: OutputFormat = "uint8array"
|
format: DataFormat,
|
||||||
): Cipher {
|
outputFormat: TOutputFormat = "uint8array" as TOutputFormat
|
||||||
|
): Cipher<TOutputFormat> {
|
||||||
const encryptionKey = KeyUtils.transform(key);
|
const encryptionKey = KeyUtils.transform(key);
|
||||||
const data = this.transformInput(plaintext);
|
const data = this.transformInput(input, format);
|
||||||
|
|
||||||
const nonce = randombytes_buf(crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
const nonce = randombytes_buf(crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
||||||
|
|
||||||
@@ -81,7 +83,7 @@ export default class Encryption {
|
|||||||
iv,
|
iv,
|
||||||
salt: encryptionKey.salt,
|
salt: encryptionKey.salt,
|
||||||
length: data.length
|
length: data.length
|
||||||
};
|
} as Cipher<TOutputFormat>;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createStream(key: SerializedKey): {
|
static createStream(key: SerializedKey): {
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
import {
|
import {
|
||||||
Cipher,
|
Cipher,
|
||||||
EncryptionKey,
|
EncryptionKey,
|
||||||
OutputFormat,
|
DataFormat,
|
||||||
Plaintext,
|
|
||||||
SerializedKey,
|
SerializedKey,
|
||||||
Chunk,
|
Chunk,
|
||||||
Output
|
Output,
|
||||||
|
Input
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export interface IStreamable {
|
export interface IStreamable {
|
||||||
@@ -33,21 +33,29 @@ export interface IStreamable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface INNCrypto {
|
export interface INNCrypto {
|
||||||
encrypt(
|
encrypt<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
plaintext: Plaintext<OutputFormat>,
|
data: Input<DataFormat>,
|
||||||
outputFormat?: OutputFormat
|
format: DataFormat,
|
||||||
): Promise<Cipher>;
|
outputFormat?: TOutputFormat
|
||||||
|
): Promise<Cipher<TOutputFormat>>;
|
||||||
|
|
||||||
decrypt<TOutputFormat extends OutputFormat>(
|
encryptMulti<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
cipherData: Cipher,
|
data: Input<DataFormat>[],
|
||||||
|
format: DataFormat,
|
||||||
|
outputFormat?: TOutputFormat
|
||||||
|
): Promise<Cipher<TOutputFormat>[]>;
|
||||||
|
|
||||||
|
decrypt<TOutputFormat extends DataFormat>(
|
||||||
|
key: SerializedKey,
|
||||||
|
cipherData: Cipher<DataFormat>,
|
||||||
outputFormat?: TOutputFormat
|
outputFormat?: TOutputFormat
|
||||||
): Promise<Output<TOutputFormat>>;
|
): Promise<Output<TOutputFormat>>;
|
||||||
|
|
||||||
decryptMulti<TOutputFormat extends OutputFormat>(
|
decryptMulti<TOutputFormat extends DataFormat>(
|
||||||
key: SerializedKey,
|
key: SerializedKey,
|
||||||
cipherData: Cipher[],
|
cipherData: Cipher<DataFormat>[],
|
||||||
outputFormat?: TOutputFormat
|
outputFormat?: TOutputFormat
|
||||||
): Promise<Output<TOutputFormat>[]>;
|
): Promise<Output<TOutputFormat>[]>;
|
||||||
|
|
||||||
|
|||||||
@@ -19,23 +19,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
import { StringOutputFormat, Uint8ArrayOutputFormat } from "@notesnook/sodium";
|
import { StringOutputFormat, Uint8ArrayOutputFormat } from "@notesnook/sodium";
|
||||||
|
|
||||||
export type OutputFormat = Uint8ArrayOutputFormat | StringOutputFormat;
|
export type DataFormat = Uint8ArrayOutputFormat | StringOutputFormat;
|
||||||
|
|
||||||
export type Cipher = {
|
export type Cipher<TFormat extends DataFormat> = {
|
||||||
format: OutputFormat;
|
format: TFormat;
|
||||||
alg: string;
|
alg: string;
|
||||||
cipher: string | Uint8Array;
|
cipher: Output<TFormat>;
|
||||||
iv: string;
|
iv: string;
|
||||||
salt: string;
|
salt: string;
|
||||||
length: number;
|
length: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Plaintext<TFormat extends OutputFormat> = {
|
export type Output<TFormat extends DataFormat> =
|
||||||
format: TFormat;
|
|
||||||
data: TFormat extends StringOutputFormat ? string : Uint8Array;
|
|
||||||
};
|
|
||||||
export type Output<TFormat extends OutputFormat> =
|
|
||||||
TFormat extends StringOutputFormat ? string : Uint8Array;
|
TFormat extends StringOutputFormat ? string : Uint8Array;
|
||||||
|
export type Input<TFormat extends DataFormat> = Output<TFormat>;
|
||||||
|
|
||||||
export type SerializedKey = {
|
export type SerializedKey = {
|
||||||
password?: string;
|
password?: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user