mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
feat: impl libsodium crypto
This commit is contained in:
87
packages/core/utils/crypto.js
Normal file
87
packages/core/utils/crypto.js
Normal file
@@ -0,0 +1,87 @@
|
||||
import _sodium from "libsodium-wrappers";
|
||||
|
||||
export async function newSodium() {
|
||||
await _sodium.ready;
|
||||
return _sodium;
|
||||
}
|
||||
|
||||
class Crypto {
|
||||
constructor() {
|
||||
this.isReady = false;
|
||||
this.sodium = _sodium;
|
||||
}
|
||||
|
||||
async init() {
|
||||
this.sodium = await newSodium();
|
||||
this.isReady = true;
|
||||
}
|
||||
|
||||
_throwIfNotReady() {
|
||||
if (!this.isReady)
|
||||
throw new Error("libsodium is not ready yet. Please call init()");
|
||||
}
|
||||
|
||||
_deriveKey(password, keyLength, salt) {
|
||||
this._throwIfNotReady();
|
||||
salt =
|
||||
salt || this.sodium.randombytes_buf(this.sodium.crypto_pwhash_SALTBYTES);
|
||||
const key = this.sodium.crypto_pwhash(
|
||||
keyLength,
|
||||
password,
|
||||
salt,
|
||||
3, // operations limit
|
||||
1024 * 1024 * 4, // memory limit (4MB)
|
||||
this.sodium.crypto_pwhash_ALG_ARGON2I13
|
||||
);
|
||||
const saltHex = this.sodium.to_hex(salt);
|
||||
this.sodium.memzero(salt);
|
||||
return { key, salt: saltHex };
|
||||
}
|
||||
|
||||
encrypt({ password, data }) {
|
||||
this._throwIfNotReady();
|
||||
const { key, salt } = this._deriveKey(
|
||||
password,
|
||||
this.sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES
|
||||
);
|
||||
const nonce = this.sodium.randombytes_buf(
|
||||
this.sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
|
||||
);
|
||||
const cipher = this.sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
data,
|
||||
undefined,
|
||||
undefined,
|
||||
nonce,
|
||||
key,
|
||||
"base64"
|
||||
);
|
||||
const iv = this.sodium.to_hex(nonce);
|
||||
this.sodium.memzero(nonce);
|
||||
this.sodium.memzero(key);
|
||||
return {
|
||||
cipher,
|
||||
iv,
|
||||
salt,
|
||||
};
|
||||
}
|
||||
|
||||
decrypt({ password, data: { salt, iv, cipher } }) {
|
||||
this._throwIfNotReady();
|
||||
const { key } = this._deriveKey(
|
||||
password,
|
||||
this.sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
||||
this.sodium.from_hex(salt)
|
||||
);
|
||||
const plainText = this.sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
undefined,
|
||||
this.sodium.from_base64(cipher),
|
||||
undefined,
|
||||
this.sodium.from_hex(iv),
|
||||
key,
|
||||
"text"
|
||||
);
|
||||
this.sodium.memzero(key);
|
||||
return plainText;
|
||||
}
|
||||
}
|
||||
export default Crypto;
|
||||
Reference in New Issue
Block a user