mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-07-10 04:21:21 +02:00
106 lines
3.0 KiB
TypeScript
106 lines
3.0 KiB
TypeScript
/*
|
|
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 { ISodium } from "@notesnook/sodium";
|
|
import {
|
|
EncryptionKey,
|
|
EncryptionKeyPair,
|
|
SerializedKey,
|
|
SerializedKeyPair
|
|
} from "./types.js";
|
|
|
|
export enum base64_variants {
|
|
ORIGINAL = 1,
|
|
ORIGINAL_NO_PADDING = 3,
|
|
URLSAFE = 5,
|
|
URLSAFE_NO_PADDING = 7
|
|
}
|
|
|
|
export default class KeyUtils {
|
|
static deriveKey(
|
|
sodium: ISodium,
|
|
password: string,
|
|
salt?: string
|
|
): EncryptionKey {
|
|
let saltBytes: Uint8Array;
|
|
if (!salt)
|
|
saltBytes = sodium.randombytes_buf(sodium.crypto_pwhash_SALTBYTES);
|
|
else {
|
|
saltBytes = sodium.from_base64(salt);
|
|
}
|
|
|
|
if (!saltBytes)
|
|
throw new Error("Could not generate bytes from the given salt.");
|
|
|
|
const key = sodium.crypto_pwhash(
|
|
sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
|
password,
|
|
saltBytes,
|
|
3, // operations limit
|
|
1024 * 1024 * 8, // memory limit (8MB)
|
|
sodium.crypto_pwhash_ALG_ARGON2I13
|
|
);
|
|
|
|
return {
|
|
key,
|
|
salt: typeof salt === "string" ? salt : sodium.to_base64(saltBytes)
|
|
};
|
|
}
|
|
|
|
static deriveKeyPair(sodium: ISodium): EncryptionKeyPair {
|
|
const keypair = sodium.crypto_box_keypair();
|
|
return {
|
|
publicKey: keypair.publicKey,
|
|
privateKey: keypair.privateKey
|
|
};
|
|
}
|
|
|
|
static exportKey(
|
|
sodium: ISodium,
|
|
password: string,
|
|
salt?: string
|
|
): SerializedKey {
|
|
const { key, salt: keySalt } = this.deriveKey(sodium, password, salt);
|
|
return { key: sodium.to_base64(key), salt: keySalt };
|
|
}
|
|
|
|
static exportKeyPair(sodium: ISodium): SerializedKeyPair {
|
|
const { publicKey, privateKey } = this.deriveKeyPair(sodium);
|
|
return {
|
|
publicKey: sodium.to_base64(publicKey),
|
|
privateKey: sodium.to_base64(privateKey)
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Takes in either a password or a serialized encryption key
|
|
* and spits out a key that can be directly used for encryption/decryption.
|
|
* @param input
|
|
*/
|
|
static transform(sodium: ISodium, input: SerializedKey): EncryptionKey {
|
|
if ("password" in input && !!input.password) {
|
|
const { password, salt } = input;
|
|
return this.deriveKey(sodium, password, salt);
|
|
} else if ("key" in input && !!input.salt && !!input.key) {
|
|
return { key: sodium.from_base64(input.key), salt: input.salt };
|
|
}
|
|
throw new Error("Invalid input.");
|
|
}
|
|
}
|