mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-23 19:49:56 +01:00
crypto: @notesnook/sodium no longer requires top-level await
This commit is contained in:
@@ -17,28 +17,21 @@ 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 {
|
||||
crypto_aead_xchacha20poly1305_ietf_decrypt,
|
||||
crypto_secretstream_xchacha20poly1305_init_pull,
|
||||
crypto_secretstream_xchacha20poly1305_pull,
|
||||
to_base64,
|
||||
from_base64,
|
||||
base64_variants,
|
||||
to_string,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_FINAL,
|
||||
from_hex
|
||||
} from "@notesnook/sodium";
|
||||
import { base64_variants, ISodium } from "@notesnook/sodium";
|
||||
import KeyUtils from "./keyutils.js";
|
||||
import { Cipher, Output, DataFormat, SerializedKey } from "./types.js";
|
||||
|
||||
export default class Decryption {
|
||||
private static transformInput(cipherData: Cipher<DataFormat>): Uint8Array {
|
||||
private static transformInput(
|
||||
sodium: ISodium,
|
||||
cipherData: Cipher<DataFormat>
|
||||
): Uint8Array {
|
||||
let input: Uint8Array | null = null;
|
||||
if (
|
||||
typeof cipherData.cipher === "string" &&
|
||||
cipherData.format === "base64"
|
||||
) {
|
||||
input = from_base64(
|
||||
input = sodium.from_base64(
|
||||
cipherData.cipher,
|
||||
base64_variants.URLSAFE_NO_PADDING
|
||||
);
|
||||
@@ -46,7 +39,7 @@ export default class Decryption {
|
||||
typeof cipherData.cipher === "string" &&
|
||||
cipherData.format === "hex"
|
||||
) {
|
||||
input = from_hex(cipherData.cipher);
|
||||
input = sodium.from_hex(cipherData.cipher);
|
||||
} else if (cipherData.cipher instanceof Uint8Array) {
|
||||
input = cipherData.cipher;
|
||||
}
|
||||
@@ -55,52 +48,51 @@ export default class Decryption {
|
||||
}
|
||||
|
||||
static decrypt<TOutputFormat extends DataFormat>(
|
||||
sodium: ISodium,
|
||||
key: SerializedKey,
|
||||
cipherData: Cipher<DataFormat>,
|
||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
||||
): Output<TOutputFormat> {
|
||||
if (!key.salt && cipherData.salt) key.salt = cipherData.salt;
|
||||
const encryptionKey = KeyUtils.transform(key);
|
||||
const encryptionKey = KeyUtils.transform(sodium, key);
|
||||
|
||||
const input = this.transformInput(cipherData);
|
||||
const plaintext = crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
const input = this.transformInput(sodium, cipherData);
|
||||
const plaintext = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
null,
|
||||
input,
|
||||
null,
|
||||
from_base64(cipherData.iv),
|
||||
sodium.from_base64(cipherData.iv),
|
||||
encryptionKey.key
|
||||
);
|
||||
|
||||
return (
|
||||
outputFormat === "base64"
|
||||
? to_base64(plaintext, base64_variants.ORIGINAL)
|
||||
? sodium.to_base64(plaintext, base64_variants.ORIGINAL)
|
||||
: outputFormat === "text"
|
||||
? to_string(plaintext)
|
||||
? sodium.to_string(plaintext)
|
||||
: plaintext
|
||||
) as Output<TOutputFormat>;
|
||||
}
|
||||
|
||||
static createStream(
|
||||
sodium: ISodium,
|
||||
header: string,
|
||||
key: SerializedKey
|
||||
): TransformStream<Uint8Array, Uint8Array> {
|
||||
const { key: _key } = KeyUtils.transform(key);
|
||||
const state = crypto_secretstream_xchacha20poly1305_init_pull(
|
||||
from_base64(header),
|
||||
const { key: _key } = KeyUtils.transform(sodium, key);
|
||||
const state = sodium.crypto_secretstream_xchacha20poly1305_init_pull(
|
||||
sodium.from_base64(header),
|
||||
_key
|
||||
);
|
||||
|
||||
return new TransformStream<Uint8Array, Uint8Array>({
|
||||
start() {},
|
||||
transform(chunk, controller) {
|
||||
const { message, tag } = crypto_secretstream_xchacha20poly1305_pull(
|
||||
state,
|
||||
chunk,
|
||||
null
|
||||
);
|
||||
const { message, tag } =
|
||||
sodium.crypto_secretstream_xchacha20poly1305_pull(state, chunk, null);
|
||||
if (!message) throw new Error("Could not decrypt chunk.");
|
||||
controller.enqueue(message);
|
||||
if (tag === crypto_secretstream_xchacha20poly1305_TAG_FINAL)
|
||||
if (tag === sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
|
||||
controller.terminate();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,30 +17,20 @@ 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 {
|
||||
crypto_aead_xchacha20poly1305_ietf_encrypt,
|
||||
crypto_secretstream_xchacha20poly1305_init_push,
|
||||
crypto_secretstream_xchacha20poly1305_push,
|
||||
randombytes_buf,
|
||||
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_FINAL,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
|
||||
to_base64,
|
||||
from_base64,
|
||||
base64_variants
|
||||
} from "@notesnook/sodium";
|
||||
import { ISodium, base64_variants } from "@notesnook/sodium";
|
||||
import KeyUtils from "./keyutils.js";
|
||||
import { Chunk, Cipher, Input, DataFormat, SerializedKey } from "./types.js";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
export default class Encryption {
|
||||
private static transformInput(
|
||||
sodium: ISodium,
|
||||
input: Input<DataFormat>,
|
||||
format: DataFormat
|
||||
): Uint8Array {
|
||||
let data: Uint8Array | null = null;
|
||||
if (typeof input === "string" && format === "base64") {
|
||||
data = from_base64(input, base64_variants.ORIGINAL);
|
||||
data = sodium.from_base64(input, base64_variants.ORIGINAL);
|
||||
} else if (typeof input === "string") {
|
||||
data = encoder.encode(input);
|
||||
} else if (input instanceof Uint8Array) {
|
||||
@@ -51,18 +41,21 @@ export default class Encryption {
|
||||
}
|
||||
|
||||
static encrypt<TOutputFormat extends DataFormat>(
|
||||
sodium: ISodium,
|
||||
key: SerializedKey,
|
||||
input: Input<DataFormat>,
|
||||
format: DataFormat,
|
||||
outputFormat: TOutputFormat = "uint8array" as TOutputFormat
|
||||
): Cipher<TOutputFormat> {
|
||||
const encryptionKey = KeyUtils.transform(key);
|
||||
const data = this.transformInput(input, format);
|
||||
const encryptionKey = KeyUtils.transform(sodium, key);
|
||||
const data = this.transformInput(sodium, input, format);
|
||||
|
||||
const nonce = randombytes_buf(crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
||||
const nonce = sodium.randombytes_buf(
|
||||
sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
|
||||
);
|
||||
|
||||
const cipher: string | Uint8Array =
|
||||
crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
data,
|
||||
null,
|
||||
null,
|
||||
@@ -72,10 +65,10 @@ export default class Encryption {
|
||||
|
||||
let output: string | Uint8Array = cipher;
|
||||
if (outputFormat === "base64") {
|
||||
output = to_base64(cipher, base64_variants.URLSAFE_NO_PADDING);
|
||||
output = sodium.to_base64(cipher, base64_variants.URLSAFE_NO_PADDING);
|
||||
}
|
||||
|
||||
const iv = to_base64(nonce);
|
||||
const iv = sodium.to_base64(nonce);
|
||||
return {
|
||||
format: outputFormat,
|
||||
alg: getAlgorithm(base64_variants.URLSAFE_NO_PADDING),
|
||||
@@ -86,15 +79,16 @@ export default class Encryption {
|
||||
} as Cipher<TOutputFormat>;
|
||||
}
|
||||
|
||||
static createStream(key: SerializedKey): {
|
||||
static createStream(
|
||||
sodium: ISodium,
|
||||
key: SerializedKey
|
||||
): {
|
||||
iv: string;
|
||||
stream: TransformStream<Chunk, Uint8Array>;
|
||||
} {
|
||||
const { key: _key } = KeyUtils.transform(key);
|
||||
const { state, header } = crypto_secretstream_xchacha20poly1305_init_push(
|
||||
_key,
|
||||
"base64"
|
||||
);
|
||||
const { key: _key } = KeyUtils.transform(sodium, key);
|
||||
const { state, header } =
|
||||
sodium.crypto_secretstream_xchacha20poly1305_init_push(_key, "base64");
|
||||
|
||||
return {
|
||||
iv: header,
|
||||
@@ -102,13 +96,13 @@ export default class Encryption {
|
||||
start() {},
|
||||
transform(chunk, controller) {
|
||||
controller.enqueue(
|
||||
crypto_secretstream_xchacha20poly1305_push(
|
||||
sodium.crypto_secretstream_xchacha20poly1305_push(
|
||||
state,
|
||||
chunk.data,
|
||||
null,
|
||||
chunk.final
|
||||
? crypto_secretstream_xchacha20poly1305_TAG_FINAL
|
||||
: crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
|
||||
? sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
|
||||
: sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
|
||||
)
|
||||
);
|
||||
if (chunk.final) controller.terminate();
|
||||
@@ -118,30 +112,6 @@ export default class Encryption {
|
||||
}
|
||||
}
|
||||
|
||||
// class EncryptionStream {
|
||||
// state: StateAddress;
|
||||
// header: string;
|
||||
// constructor(key: EncryptionKey) {
|
||||
// const { state, header } = crypto_secretstream_xchacha20poly1305_init_push(
|
||||
// key.key,
|
||||
// "base64"
|
||||
// );
|
||||
// this.state = state;
|
||||
// this.header = header;
|
||||
// }
|
||||
|
||||
// write(chunk: Uint8Array, final?: boolean): Uint8Array {
|
||||
// return crypto_secretstream_xchacha20poly1305_push(
|
||||
// this.state,
|
||||
// chunk,
|
||||
// null,
|
||||
// final
|
||||
// ? crypto_secretstream_xchacha20poly1305_TAG_FINAL
|
||||
// : crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
function getAlgorithm(base64Variant: base64_variants) {
|
||||
//Template: encryptionAlgorithm-kdfAlgorithm-base64variant
|
||||
return `xcha-argon2i13-${base64Variant}`;
|
||||
|
||||
@@ -17,7 +17,7 @@ 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 { initialize } from "@notesnook/sodium";
|
||||
import { ISodium, Sodium } from "@notesnook/sodium";
|
||||
import Decryption from "./decryption.js";
|
||||
import Encryption from "./encryption.js";
|
||||
import { INNCrypto } from "./interfaces.js";
|
||||
@@ -34,10 +34,11 @@ import {
|
||||
|
||||
export class NNCrypto implements INNCrypto {
|
||||
private isReady = false;
|
||||
private sodium: ISodium = new Sodium();
|
||||
|
||||
private async init() {
|
||||
if (this.isReady) return;
|
||||
await initialize();
|
||||
await this.sodium.initialize();
|
||||
this.isReady = true;
|
||||
}
|
||||
|
||||
@@ -49,6 +50,7 @@ export class NNCrypto implements INNCrypto {
|
||||
): Promise<Cipher<TOutputFormat>> {
|
||||
await this.init();
|
||||
return Encryption.encrypt(
|
||||
this.sodium,
|
||||
key,
|
||||
input,
|
||||
format,
|
||||
@@ -64,7 +66,7 @@ export class NNCrypto implements INNCrypto {
|
||||
): Promise<Cipher<TOutputFormat>[]> {
|
||||
await this.init();
|
||||
return items.map((data) =>
|
||||
Encryption.encrypt(key, data, format, outputFormat)
|
||||
Encryption.encrypt(this.sodium, key, data, format, outputFormat)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -74,7 +76,7 @@ export class NNCrypto implements INNCrypto {
|
||||
outputFormat: TOutputFormat = "text" as TOutputFormat
|
||||
): Promise<Output<TOutputFormat>> {
|
||||
await this.init();
|
||||
return Decryption.decrypt(key, cipherData, outputFormat);
|
||||
return Decryption.decrypt(this.sodium, key, cipherData, outputFormat);
|
||||
}
|
||||
|
||||
async decryptMulti<TOutputFormat extends DataFormat>(
|
||||
@@ -85,88 +87,37 @@ export class NNCrypto implements INNCrypto {
|
||||
await this.init();
|
||||
const decryptedItems: Output<TOutputFormat>[] = [];
|
||||
for (const cipherData of items) {
|
||||
decryptedItems.push(Decryption.decrypt(key, cipherData, outputFormat));
|
||||
decryptedItems.push(
|
||||
Decryption.decrypt(this.sodium, key, cipherData, outputFormat)
|
||||
);
|
||||
}
|
||||
return decryptedItems;
|
||||
}
|
||||
|
||||
async hash(password: string, salt: string): Promise<string> {
|
||||
await this.init();
|
||||
return Password.hash(password, salt);
|
||||
return Password.hash(this.sodium, password, salt);
|
||||
}
|
||||
|
||||
async deriveKey(password: string, salt?: string): Promise<EncryptionKey> {
|
||||
await this.init();
|
||||
return KeyUtils.deriveKey(password, salt);
|
||||
return KeyUtils.deriveKey(this.sodium, password, salt);
|
||||
}
|
||||
|
||||
async exportKey(password: string, salt?: string): Promise<SerializedKey> {
|
||||
await this.init();
|
||||
return KeyUtils.exportKey(password, salt);
|
||||
return KeyUtils.exportKey(this.sodium, password, salt);
|
||||
}
|
||||
|
||||
async createEncryptionStream(key: SerializedKey) {
|
||||
await this.init();
|
||||
return Encryption.createStream(key);
|
||||
|
||||
// // eslint-disable-next-line no-constant-condition
|
||||
// while (true) {
|
||||
// const chunk = await stream.read();
|
||||
// if (!chunk) break;
|
||||
|
||||
// const { data, final } = chunk;
|
||||
// if (!data) break;
|
||||
|
||||
// const encryptedChunk: Chunk = {
|
||||
// data: encryptionStream.write(data, final),
|
||||
// final
|
||||
// };
|
||||
// await stream.write(encryptedChunk);
|
||||
|
||||
// if (final) break;
|
||||
// }
|
||||
// return encryptionStream.header;
|
||||
return Encryption.createStream(this.sodium, key);
|
||||
}
|
||||
|
||||
async createDecryptionStream(key: SerializedKey, iv: string) {
|
||||
await this.init();
|
||||
return Decryption.createStream(iv, key);
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
// while (true) {
|
||||
// const chunk = await stream.read();
|
||||
// if (!chunk) break;
|
||||
|
||||
// const { data, final } = chunk;
|
||||
// if (!data) break;
|
||||
|
||||
// const decryptedChunk: Chunk = {
|
||||
// data: decryptionStream.read(data),
|
||||
// final
|
||||
// };
|
||||
// await stream.write(decryptedChunk);
|
||||
|
||||
// if (final) break;
|
||||
// }
|
||||
return Decryption.createStream(this.sodium, iv, key);
|
||||
}
|
||||
|
||||
// async encryptStream(
|
||||
// key: SerializedKey,
|
||||
// stream: IStreamable,
|
||||
// _streamId?: string
|
||||
// ): Promise<string> {
|
||||
// await this.init();
|
||||
// return await this.createEncryptionStream(key, stream);
|
||||
// }
|
||||
|
||||
// async decryptStream(
|
||||
// key: SerializedKey,
|
||||
// iv: string,
|
||||
// stream: IStreamable,
|
||||
// _streamId?: string
|
||||
// ): Promise<void> {
|
||||
// await this.init();
|
||||
// await this.createDecryptionStream(iv, key, stream);
|
||||
// }
|
||||
}
|
||||
|
||||
export * from "./types.js";
|
||||
|
||||
@@ -17,46 +17,47 @@ 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 {
|
||||
from_base64,
|
||||
to_base64,
|
||||
randombytes_buf,
|
||||
crypto_pwhash,
|
||||
crypto_pwhash_SALTBYTES,
|
||||
crypto_pwhash_ALG_ARGON2I13,
|
||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES
|
||||
} from "@notesnook/sodium";
|
||||
import { ISodium } from "@notesnook/sodium";
|
||||
import { EncryptionKey, SerializedKey } from "./types.js";
|
||||
|
||||
export default class KeyUtils {
|
||||
static deriveKey(password: string, salt?: string): EncryptionKey {
|
||||
static deriveKey(
|
||||
sodium: ISodium,
|
||||
password: string,
|
||||
salt?: string
|
||||
): EncryptionKey {
|
||||
let saltBytes: Uint8Array;
|
||||
if (!salt) saltBytes = randombytes_buf(crypto_pwhash_SALTBYTES);
|
||||
if (!salt)
|
||||
saltBytes = sodium.randombytes_buf(sodium.crypto_pwhash_SALTBYTES);
|
||||
else {
|
||||
saltBytes = from_base64(salt);
|
||||
saltBytes = sodium.from_base64(salt);
|
||||
}
|
||||
|
||||
if (!saltBytes)
|
||||
throw new Error("Could not generate bytes from the given salt.");
|
||||
|
||||
const key = crypto_pwhash(
|
||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
||||
const key = sodium.crypto_pwhash(
|
||||
sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
||||
password,
|
||||
saltBytes,
|
||||
3, // operations limit
|
||||
1024 * 1024 * 8, // memory limit (8MB)
|
||||
crypto_pwhash_ALG_ARGON2I13
|
||||
sodium.crypto_pwhash_ALG_ARGON2I13
|
||||
);
|
||||
|
||||
return {
|
||||
key,
|
||||
salt: typeof salt === "string" ? salt : to_base64(saltBytes)
|
||||
salt: typeof salt === "string" ? salt : sodium.to_base64(saltBytes)
|
||||
};
|
||||
}
|
||||
|
||||
static exportKey(password: string, salt?: string): SerializedKey {
|
||||
const { key, salt: keySalt } = this.deriveKey(password, salt);
|
||||
return { key: to_base64(key), salt: keySalt };
|
||||
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 };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,12 +65,12 @@ export default class KeyUtils {
|
||||
* and spits out a key that can be directly used for encryption/decryption.
|
||||
* @param input
|
||||
*/
|
||||
static transform(input: SerializedKey): EncryptionKey {
|
||||
static transform(sodium: ISodium, input: SerializedKey): EncryptionKey {
|
||||
if ("password" in input && !!input.password) {
|
||||
const { password, salt } = input;
|
||||
return this.deriveKey(password, salt);
|
||||
return this.deriveKey(sodium, password, salt);
|
||||
} else if ("key" in input && !!input.salt && !!input.key) {
|
||||
return { key: from_base64(input.key), salt: input.salt };
|
||||
return { key: sodium.from_base64(input.key), salt: input.salt };
|
||||
}
|
||||
throw new Error("Invalid input.");
|
||||
}
|
||||
|
||||
@@ -17,23 +17,21 @@ 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 {
|
||||
crypto_generichash,
|
||||
crypto_pwhash,
|
||||
crypto_pwhash_ALG_ARGON2ID13,
|
||||
crypto_pwhash_SALTBYTES
|
||||
} from "@notesnook/sodium";
|
||||
import { ISodium } from "@notesnook/sodium";
|
||||
|
||||
export default class Password {
|
||||
static hash(password: string, salt: string): string {
|
||||
const saltBytes = crypto_generichash(crypto_pwhash_SALTBYTES, salt);
|
||||
const hash = crypto_pwhash(
|
||||
static hash(sodium: ISodium, password: string, salt: string): string {
|
||||
const saltBytes = sodium.crypto_generichash(
|
||||
sodium.crypto_pwhash_SALTBYTES,
|
||||
salt
|
||||
);
|
||||
const hash = sodium.crypto_pwhash(
|
||||
32,
|
||||
password,
|
||||
saltBytes,
|
||||
3, // operations limit
|
||||
1024 * 1024 * 64, // memory limit (8MB)
|
||||
crypto_pwhash_ALG_ARGON2ID13,
|
||||
sodium.crypto_pwhash_ALG_ARGON2ID13,
|
||||
"base64"
|
||||
);
|
||||
return hash;
|
||||
|
||||
@@ -16,8 +16,9 @@ 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 * as browser from "../src/browser.js";
|
||||
import * as node from "../src/node.js";
|
||||
|
||||
import { Sodium as BrowserSodium } from "../src/browser";
|
||||
import { Sodium as NodeSodium } from "../src/node";
|
||||
import benny from "benny";
|
||||
import {
|
||||
decrypt,
|
||||
@@ -25,7 +26,10 @@ import {
|
||||
getKey,
|
||||
hash,
|
||||
streamingEncrypt
|
||||
} from "../tests/utils.js";
|
||||
} from "../tests/utils";
|
||||
|
||||
const browser = new BrowserSodium();
|
||||
const node = new NodeSodium();
|
||||
|
||||
async function main() {
|
||||
await browser.initialize();
|
||||
|
||||
@@ -18,45 +18,125 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import sodium from "libsodium-wrappers-sumo";
|
||||
import { base64_variants, type ISodium } from "./types";
|
||||
|
||||
export async function initialize() {
|
||||
await sodium.ready;
|
||||
}
|
||||
export class Sodium implements ISodium {
|
||||
async initialize() {
|
||||
await sodium.ready;
|
||||
}
|
||||
|
||||
export {
|
||||
crypto_generichash,
|
||||
crypto_pwhash,
|
||||
crypto_pwhash_ALG_ARGON2ID13,
|
||||
crypto_pwhash_SALTBYTES,
|
||||
crypto_pwhash_ALG_ARGON2I13,
|
||||
crypto_pwhash_ALG_DEFAULT,
|
||||
crypto_pwhash_OPSLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_OPSLIMIT_MODERATE,
|
||||
crypto_pwhash_OPSLIMIT_SENSITIVE,
|
||||
crypto_pwhash_MEMLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_MEMLIMIT_MODERATE,
|
||||
crypto_pwhash_MEMLIMIT_SENSITIVE,
|
||||
get crypto_generichash() {
|
||||
return sodium.crypto_generichash;
|
||||
}
|
||||
|
||||
get crypto_pwhash() {
|
||||
return sodium.crypto_pwhash;
|
||||
}
|
||||
|
||||
get crypto_pwhash_ALG_ARGON2ID13() {
|
||||
return sodium.crypto_pwhash_ALG_ARGON2ID13;
|
||||
}
|
||||
get crypto_pwhash_SALTBYTES() {
|
||||
return sodium.crypto_pwhash_SALTBYTES;
|
||||
}
|
||||
get crypto_pwhash_ALG_ARGON2I13() {
|
||||
return sodium.crypto_pwhash_ALG_ARGON2I13;
|
||||
}
|
||||
get crypto_pwhash_ALG_DEFAULT() {
|
||||
return sodium.crypto_pwhash_ALG_DEFAULT;
|
||||
}
|
||||
get crypto_pwhash_OPSLIMIT_INTERACTIVE() {
|
||||
return sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE;
|
||||
}
|
||||
get crypto_pwhash_OPSLIMIT_MODERATE() {
|
||||
return sodium.crypto_pwhash_OPSLIMIT_MODERATE;
|
||||
}
|
||||
get crypto_pwhash_OPSLIMIT_SENSITIVE() {
|
||||
return sodium.crypto_pwhash_OPSLIMIT_SENSITIVE;
|
||||
}
|
||||
get crypto_pwhash_MEMLIMIT_INTERACTIVE() {
|
||||
return sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE;
|
||||
}
|
||||
get crypto_pwhash_MEMLIMIT_MODERATE() {
|
||||
return sodium.crypto_pwhash_MEMLIMIT_MODERATE;
|
||||
}
|
||||
get crypto_pwhash_MEMLIMIT_SENSITIVE() {
|
||||
return sodium.crypto_pwhash_MEMLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
// helpers
|
||||
from_base64,
|
||||
to_base64,
|
||||
randombytes_buf,
|
||||
to_string,
|
||||
from_hex,
|
||||
base64_variants,
|
||||
from_base64(input: string, variant?: base64_variants) {
|
||||
return sodium.from_base64(
|
||||
input,
|
||||
variant ? convertVariant(variant) : undefined
|
||||
);
|
||||
}
|
||||
to_base64(input: string | Uint8Array, variant?: base64_variants): string {
|
||||
return sodium.to_base64(
|
||||
input,
|
||||
variant ? convertVariant(variant) : undefined
|
||||
);
|
||||
}
|
||||
get randombytes_buf() {
|
||||
return sodium.randombytes_buf;
|
||||
}
|
||||
get to_string() {
|
||||
return sodium.to_string;
|
||||
}
|
||||
get from_hex() {
|
||||
return sodium.from_hex;
|
||||
}
|
||||
|
||||
// aead
|
||||
get crypto_aead_xchacha20poly1305_ietf_KEYBYTES() {
|
||||
return sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
|
||||
}
|
||||
get crypto_aead_xchacha20poly1305_ietf_encrypt() {
|
||||
return sodium.crypto_aead_xchacha20poly1305_ietf_encrypt;
|
||||
}
|
||||
get crypto_aead_xchacha20poly1305_ietf_decrypt() {
|
||||
return sodium.crypto_aead_xchacha20poly1305_ietf_decrypt;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_init_push() {
|
||||
return sodium.crypto_secretstream_xchacha20poly1305_init_push;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_push() {
|
||||
return sodium.crypto_secretstream_xchacha20poly1305_push;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_init_pull() {
|
||||
return sodium.crypto_secretstream_xchacha20poly1305_init_pull;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_pull() {
|
||||
return sodium.crypto_secretstream_xchacha20poly1305_pull;
|
||||
}
|
||||
get crypto_aead_xchacha20poly1305_ietf_NPUBBYTES() {
|
||||
return sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_TAG_FINAL() {
|
||||
return sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_TAG_MESSAGE() {
|
||||
return sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
function convertVariant(variant: base64_variants): sodium.base64_variants {
|
||||
switch (variant) {
|
||||
case base64_variants.ORIGINAL:
|
||||
return sodium.base64_variants.ORIGINAL;
|
||||
case base64_variants.ORIGINAL_NO_PADDING:
|
||||
return sodium.base64_variants.ORIGINAL_NO_PADDING;
|
||||
case base64_variants.URLSAFE:
|
||||
return sodium.base64_variants.URLSAFE;
|
||||
case base64_variants.URLSAFE_NO_PADDING:
|
||||
return sodium.base64_variants.URLSAFE_NO_PADDING;
|
||||
}
|
||||
}
|
||||
export { base64_variants, ISodium };
|
||||
export {
|
||||
type StateAddress,
|
||||
type Uint8ArrayOutputFormat,
|
||||
type StringOutputFormat,
|
||||
|
||||
// aead
|
||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
||||
crypto_aead_xchacha20poly1305_ietf_encrypt,
|
||||
crypto_aead_xchacha20poly1305_ietf_decrypt,
|
||||
crypto_secretstream_xchacha20poly1305_init_push,
|
||||
crypto_secretstream_xchacha20poly1305_push,
|
||||
crypto_secretstream_xchacha20poly1305_init_pull,
|
||||
crypto_secretstream_xchacha20poly1305_pull,
|
||||
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_FINAL,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
|
||||
type MessageTag,
|
||||
type StringMessageTag
|
||||
} from "libsodium-wrappers-sumo";
|
||||
|
||||
@@ -32,18 +32,27 @@ import {
|
||||
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_ABYTES,
|
||||
crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_TAGBYTES
|
||||
crypto_secretstream_xchacha20poly1305_TAGBYTES,
|
||||
crypto_pwhash_ALG_ARGON2ID13,
|
||||
crypto_pwhash_SALTBYTES,
|
||||
crypto_pwhash_ALG_ARGON2I13,
|
||||
crypto_pwhash_ALG_DEFAULT,
|
||||
crypto_pwhash_OPSLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_OPSLIMIT_MODERATE,
|
||||
crypto_pwhash_OPSLIMIT_SENSITIVE,
|
||||
crypto_pwhash_MEMLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_MEMLIMIT_MODERATE,
|
||||
crypto_pwhash_MEMLIMIT_SENSITIVE,
|
||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
||||
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_FINAL,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
|
||||
} from "sodium-native";
|
||||
import { Buffer } from "node:buffer";
|
||||
import { base64_variants, ISodium } from "./types";
|
||||
|
||||
export type Uint8ArrayOutputFormat = "uint8array";
|
||||
export type StringOutputFormat = "text" | "hex" | "base64";
|
||||
export enum base64_variants {
|
||||
ORIGINAL = 1,
|
||||
ORIGINAL_NO_PADDING = 3,
|
||||
URLSAFE = 5,
|
||||
URLSAFE_NO_PADDING = 7
|
||||
}
|
||||
export type StateAddress = { name: string };
|
||||
export interface MessageTag {
|
||||
message: Uint8Array;
|
||||
@@ -54,9 +63,7 @@ export interface StringMessageTag {
|
||||
tag: number;
|
||||
}
|
||||
|
||||
export async function initialize() {}
|
||||
|
||||
export function crypto_pwhash(
|
||||
function crypto_pwhash(
|
||||
keyLength: number,
|
||||
password: string | Uint8Array,
|
||||
salt: Uint8Array,
|
||||
@@ -65,7 +72,7 @@ export function crypto_pwhash(
|
||||
algorithm: number,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): Uint8Array;
|
||||
export function crypto_pwhash(
|
||||
function crypto_pwhash(
|
||||
keyLength: number,
|
||||
password: string | Uint8Array,
|
||||
salt: Uint8Array,
|
||||
@@ -74,7 +81,7 @@ export function crypto_pwhash(
|
||||
algorithm: number,
|
||||
outputFormat: StringOutputFormat
|
||||
): string;
|
||||
export function crypto_pwhash(
|
||||
function crypto_pwhash(
|
||||
keyLength: number,
|
||||
password: string | Uint8Array,
|
||||
salt: Uint8Array,
|
||||
@@ -98,19 +105,19 @@ export function crypto_pwhash(
|
||||
);
|
||||
}
|
||||
|
||||
export function crypto_generichash(
|
||||
function crypto_generichash(
|
||||
hash_length: number,
|
||||
message: string | Uint8Array,
|
||||
key?: string | Uint8Array | null,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): Uint8Array;
|
||||
export function crypto_generichash(
|
||||
function crypto_generichash(
|
||||
hash_length: number,
|
||||
message: string | Uint8Array,
|
||||
key: string | Uint8Array | null,
|
||||
outputFormat: StringOutputFormat
|
||||
): string;
|
||||
export function crypto_generichash(
|
||||
function crypto_generichash(
|
||||
hash_length: number,
|
||||
message: string | Uint8Array,
|
||||
key?: string | Uint8Array | null,
|
||||
@@ -131,7 +138,7 @@ export function crypto_generichash(
|
||||
);
|
||||
}
|
||||
|
||||
export function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
message: string | Uint8Array,
|
||||
additional_data: string | Uint8Array | null,
|
||||
secret_nonce: string | Uint8Array | null,
|
||||
@@ -139,7 +146,7 @@ export function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
key: Uint8Array,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): Uint8Array;
|
||||
export function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
message: string | Uint8Array,
|
||||
additional_data: string | Uint8Array | null,
|
||||
secret_nonce: string | Uint8Array | null,
|
||||
@@ -147,7 +154,7 @@ export function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
key: Uint8Array,
|
||||
outputFormat: StringOutputFormat
|
||||
): string;
|
||||
export function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
message: string | Uint8Array,
|
||||
additional_data: string | Uint8Array | null,
|
||||
secret_nonce: string | Uint8Array | null,
|
||||
@@ -171,15 +178,15 @@ export function crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
);
|
||||
}
|
||||
|
||||
export function crypto_secretstream_xchacha20poly1305_init_push(
|
||||
function crypto_secretstream_xchacha20poly1305_init_push(
|
||||
key: Uint8Array,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): { state: StateAddress; header: Uint8Array };
|
||||
export function crypto_secretstream_xchacha20poly1305_init_push(
|
||||
function crypto_secretstream_xchacha20poly1305_init_push(
|
||||
key: Uint8Array,
|
||||
outputFormat: StringOutputFormat
|
||||
): { state: StateAddress; header: string };
|
||||
export function crypto_secretstream_xchacha20poly1305_init_push(
|
||||
function crypto_secretstream_xchacha20poly1305_init_push(
|
||||
key: Uint8Array,
|
||||
outputFormat?: StringOutputFormat | Uint8ArrayOutputFormat | null
|
||||
): { state: StateAddress; header: string | Uint8Array } {
|
||||
@@ -198,21 +205,21 @@ export function crypto_secretstream_xchacha20poly1305_init_push(
|
||||
return { state: state as unknown as StateAddress, header };
|
||||
}
|
||||
|
||||
export function crypto_secretstream_xchacha20poly1305_push(
|
||||
function crypto_secretstream_xchacha20poly1305_push(
|
||||
state_address: StateAddress,
|
||||
message_chunk: string | Uint8Array,
|
||||
ad: string | Uint8Array | null,
|
||||
tag: number,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): Uint8Array;
|
||||
export function crypto_secretstream_xchacha20poly1305_push(
|
||||
function crypto_secretstream_xchacha20poly1305_push(
|
||||
state_address: StateAddress,
|
||||
message_chunk: string | Uint8Array,
|
||||
ad: string | Uint8Array | null,
|
||||
tag: number,
|
||||
outputFormat: StringOutputFormat
|
||||
): string;
|
||||
export function crypto_secretstream_xchacha20poly1305_push(
|
||||
function crypto_secretstream_xchacha20poly1305_push(
|
||||
state_address: StateAddress,
|
||||
message_chunk: string | Uint8Array,
|
||||
ad: string | Uint8Array | null,
|
||||
@@ -234,7 +241,7 @@ export function crypto_secretstream_xchacha20poly1305_push(
|
||||
);
|
||||
}
|
||||
|
||||
export function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
secret_nonce: string | Uint8Array | null,
|
||||
ciphertext: string | Uint8Array,
|
||||
additional_data: string | Uint8Array | null,
|
||||
@@ -242,7 +249,7 @@ export function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
key: Uint8Array,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): Uint8Array;
|
||||
export function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
secret_nonce: string | Uint8Array | null,
|
||||
ciphertext: string | Uint8Array,
|
||||
additional_data: string | Uint8Array | null,
|
||||
@@ -250,7 +257,7 @@ export function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
key: Uint8Array,
|
||||
outputFormat: StringOutputFormat
|
||||
): string;
|
||||
export function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
_secret_nonce: string | Uint8Array | null,
|
||||
ciphertext: string | Uint8Array,
|
||||
additional_data: string | Uint8Array | null,
|
||||
@@ -274,7 +281,7 @@ export function crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
);
|
||||
}
|
||||
|
||||
export function crypto_secretstream_xchacha20poly1305_init_pull(
|
||||
function crypto_secretstream_xchacha20poly1305_init_pull(
|
||||
header: Uint8Array,
|
||||
key: Uint8Array
|
||||
): StateAddress {
|
||||
@@ -287,19 +294,19 @@ export function crypto_secretstream_xchacha20poly1305_init_pull(
|
||||
return state as unknown as StateAddress;
|
||||
}
|
||||
|
||||
export function crypto_secretstream_xchacha20poly1305_pull(
|
||||
function crypto_secretstream_xchacha20poly1305_pull(
|
||||
state_address: StateAddress,
|
||||
cipher: string | Uint8Array,
|
||||
ad?: string | Uint8Array | null,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): MessageTag;
|
||||
export function crypto_secretstream_xchacha20poly1305_pull(
|
||||
function crypto_secretstream_xchacha20poly1305_pull(
|
||||
state_address: StateAddress,
|
||||
cipher: string | Uint8Array,
|
||||
ad: string | Uint8Array | null,
|
||||
outputFormat: StringOutputFormat
|
||||
): StringMessageTag;
|
||||
export function crypto_secretstream_xchacha20poly1305_pull(
|
||||
function crypto_secretstream_xchacha20poly1305_pull(
|
||||
state_address: StateAddress,
|
||||
ciphertext: string | Uint8Array,
|
||||
ad?: string | Uint8Array | null,
|
||||
@@ -322,15 +329,15 @@ export function crypto_secretstream_xchacha20poly1305_pull(
|
||||
return { message, tag: tag.readUInt8() } as MessageTag | StringMessageTag;
|
||||
}
|
||||
|
||||
export function randombytes_buf(
|
||||
function randombytes_buf(
|
||||
length: number,
|
||||
outputFormat?: Uint8ArrayOutputFormat | null
|
||||
): Uint8Array;
|
||||
export function randombytes_buf(
|
||||
function randombytes_buf(
|
||||
length: number,
|
||||
outputFormat: StringOutputFormat
|
||||
): string;
|
||||
export function randombytes_buf(
|
||||
function randombytes_buf(
|
||||
length: number,
|
||||
outputFormat?: StringOutputFormat | Uint8ArrayOutputFormat | null
|
||||
): string | Uint8Array {
|
||||
@@ -341,10 +348,7 @@ export function randombytes_buf(
|
||||
);
|
||||
}
|
||||
|
||||
export function from_base64(
|
||||
input: string,
|
||||
variant?: base64_variants
|
||||
): Uint8Array {
|
||||
function from_base64(input: string, variant?: base64_variants): Uint8Array {
|
||||
return new Uint8Array(
|
||||
Buffer.from(
|
||||
variant === base64_variants.URLSAFE_NO_PADDING ||
|
||||
@@ -359,7 +363,7 @@ export function from_base64(
|
||||
);
|
||||
}
|
||||
|
||||
export function to_base64(
|
||||
function to_base64(
|
||||
input: string | Uint8Array,
|
||||
variant: base64_variants = base64_variants.URLSAFE_NO_PADDING
|
||||
): string {
|
||||
@@ -377,33 +381,16 @@ export function to_base64(
|
||||
: base64;
|
||||
}
|
||||
|
||||
export function from_hex(input: string): Uint8Array {
|
||||
function from_hex(input: string): Uint8Array {
|
||||
return new Uint8Array(Buffer.from(input, "hex"));
|
||||
}
|
||||
|
||||
export function to_string(input: Uint8Array): string {
|
||||
function to_string(input: Uint8Array): string {
|
||||
return Buffer.from(input, input.byteOffset, input.byteLength).toString(
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
crypto_pwhash_ALG_ARGON2ID13,
|
||||
crypto_pwhash_SALTBYTES,
|
||||
crypto_pwhash_ALG_ARGON2I13,
|
||||
crypto_pwhash_ALG_DEFAULT,
|
||||
crypto_pwhash_OPSLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_OPSLIMIT_MODERATE,
|
||||
crypto_pwhash_OPSLIMIT_SENSITIVE,
|
||||
crypto_pwhash_MEMLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_MEMLIMIT_MODERATE,
|
||||
crypto_pwhash_MEMLIMIT_SENSITIVE,
|
||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
||||
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_FINAL,
|
||||
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
|
||||
} from "sodium-native";
|
||||
|
||||
type ToBufferInput = string | Uint8Array | null | undefined;
|
||||
type ToBufferResult<TInput extends ToBufferInput> = TInput extends
|
||||
| undefined
|
||||
@@ -461,3 +448,97 @@ function trimPadding(str: string): string {
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
export class Sodium implements ISodium {
|
||||
async initialize() {}
|
||||
|
||||
get crypto_generichash() {
|
||||
return crypto_generichash;
|
||||
}
|
||||
|
||||
get crypto_pwhash() {
|
||||
return crypto_pwhash;
|
||||
}
|
||||
|
||||
get crypto_pwhash_ALG_ARGON2ID13() {
|
||||
return crypto_pwhash_ALG_ARGON2ID13;
|
||||
}
|
||||
get crypto_pwhash_SALTBYTES() {
|
||||
return crypto_pwhash_SALTBYTES;
|
||||
}
|
||||
get crypto_pwhash_ALG_ARGON2I13() {
|
||||
return crypto_pwhash_ALG_ARGON2I13;
|
||||
}
|
||||
get crypto_pwhash_ALG_DEFAULT() {
|
||||
return crypto_pwhash_ALG_DEFAULT;
|
||||
}
|
||||
get crypto_pwhash_OPSLIMIT_INTERACTIVE() {
|
||||
return crypto_pwhash_OPSLIMIT_INTERACTIVE;
|
||||
}
|
||||
get crypto_pwhash_OPSLIMIT_MODERATE() {
|
||||
return crypto_pwhash_OPSLIMIT_MODERATE;
|
||||
}
|
||||
get crypto_pwhash_OPSLIMIT_SENSITIVE() {
|
||||
return crypto_pwhash_OPSLIMIT_SENSITIVE;
|
||||
}
|
||||
get crypto_pwhash_MEMLIMIT_INTERACTIVE() {
|
||||
return crypto_pwhash_MEMLIMIT_INTERACTIVE;
|
||||
}
|
||||
get crypto_pwhash_MEMLIMIT_MODERATE() {
|
||||
return crypto_pwhash_MEMLIMIT_MODERATE;
|
||||
}
|
||||
get crypto_pwhash_MEMLIMIT_SENSITIVE() {
|
||||
return crypto_pwhash_MEMLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
// helpers
|
||||
get from_base64() {
|
||||
return from_base64;
|
||||
}
|
||||
get to_base64() {
|
||||
return to_base64;
|
||||
}
|
||||
get randombytes_buf() {
|
||||
return randombytes_buf;
|
||||
}
|
||||
get to_string() {
|
||||
return to_string;
|
||||
}
|
||||
get from_hex() {
|
||||
return from_hex;
|
||||
}
|
||||
|
||||
// aead
|
||||
get crypto_aead_xchacha20poly1305_ietf_KEYBYTES() {
|
||||
return crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
|
||||
}
|
||||
get crypto_aead_xchacha20poly1305_ietf_encrypt() {
|
||||
return crypto_aead_xchacha20poly1305_ietf_encrypt;
|
||||
}
|
||||
get crypto_aead_xchacha20poly1305_ietf_decrypt() {
|
||||
return crypto_aead_xchacha20poly1305_ietf_decrypt;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_init_push() {
|
||||
return crypto_secretstream_xchacha20poly1305_init_push;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_push() {
|
||||
return crypto_secretstream_xchacha20poly1305_push;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_init_pull() {
|
||||
return crypto_secretstream_xchacha20poly1305_init_pull;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_pull() {
|
||||
return crypto_secretstream_xchacha20poly1305_pull;
|
||||
}
|
||||
get crypto_aead_xchacha20poly1305_ietf_NPUBBYTES() {
|
||||
return crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_TAG_FINAL() {
|
||||
return crypto_secretstream_xchacha20poly1305_TAG_FINAL;
|
||||
}
|
||||
get crypto_secretstream_xchacha20poly1305_TAG_MESSAGE() {
|
||||
return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
export { base64_variants, type ISodium };
|
||||
|
||||
64
packages/sodium/src/types.ts
Normal file
64
packages/sodium/src/types.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 type sodium from "libsodium-wrappers-sumo";
|
||||
|
||||
export enum base64_variants {
|
||||
ORIGINAL = 1,
|
||||
ORIGINAL_NO_PADDING = 3,
|
||||
URLSAFE = 5,
|
||||
URLSAFE_NO_PADDING = 7
|
||||
}
|
||||
|
||||
export interface ISodium {
|
||||
initialize(): Promise<void>;
|
||||
|
||||
get crypto_generichash(): typeof sodium.crypto_generichash;
|
||||
|
||||
get crypto_pwhash(): typeof sodium.crypto_pwhash;
|
||||
get crypto_pwhash_ALG_ARGON2ID13(): typeof sodium.crypto_pwhash_ALG_ARGON2ID13;
|
||||
get crypto_pwhash_SALTBYTES(): typeof sodium.crypto_pwhash_SALTBYTES;
|
||||
get crypto_pwhash_ALG_ARGON2I13(): typeof sodium.crypto_pwhash_ALG_ARGON2I13;
|
||||
get crypto_pwhash_ALG_DEFAULT(): typeof sodium.crypto_pwhash_ALG_DEFAULT;
|
||||
get crypto_pwhash_OPSLIMIT_INTERACTIVE(): typeof sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE;
|
||||
get crypto_pwhash_OPSLIMIT_MODERATE(): typeof sodium.crypto_pwhash_OPSLIMIT_MODERATE;
|
||||
get crypto_pwhash_OPSLIMIT_SENSITIVE(): typeof sodium.crypto_pwhash_OPSLIMIT_SENSITIVE;
|
||||
get crypto_pwhash_MEMLIMIT_INTERACTIVE(): typeof sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE;
|
||||
get crypto_pwhash_MEMLIMIT_MODERATE(): typeof sodium.crypto_pwhash_MEMLIMIT_MODERATE;
|
||||
get crypto_pwhash_MEMLIMIT_SENSITIVE(): typeof sodium.crypto_pwhash_MEMLIMIT_SENSITIVE;
|
||||
|
||||
// helpers
|
||||
from_base64(input: string, variant?: base64_variants): Uint8Array;
|
||||
to_base64(input: string | Uint8Array, variant?: base64_variants): string;
|
||||
get randombytes_buf(): typeof sodium.randombytes_buf;
|
||||
get to_string(): typeof sodium.to_string;
|
||||
get from_hex(): typeof sodium.from_hex;
|
||||
|
||||
// aead
|
||||
get crypto_aead_xchacha20poly1305_ietf_KEYBYTES(): typeof sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
|
||||
get crypto_aead_xchacha20poly1305_ietf_encrypt(): typeof sodium.crypto_aead_xchacha20poly1305_ietf_encrypt;
|
||||
get crypto_aead_xchacha20poly1305_ietf_decrypt(): typeof sodium.crypto_aead_xchacha20poly1305_ietf_decrypt;
|
||||
get crypto_secretstream_xchacha20poly1305_init_push(): typeof sodium.crypto_secretstream_xchacha20poly1305_init_push;
|
||||
get crypto_secretstream_xchacha20poly1305_push(): typeof sodium.crypto_secretstream_xchacha20poly1305_push;
|
||||
get crypto_secretstream_xchacha20poly1305_init_pull(): typeof sodium.crypto_secretstream_xchacha20poly1305_init_pull;
|
||||
get crypto_secretstream_xchacha20poly1305_pull(): typeof sodium.crypto_secretstream_xchacha20poly1305_pull;
|
||||
get crypto_aead_xchacha20poly1305_ietf_NPUBBYTES(): typeof sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
|
||||
get crypto_secretstream_xchacha20poly1305_TAG_FINAL(): typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL;
|
||||
get crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(): typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
|
||||
}
|
||||
@@ -17,8 +17,9 @@ 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 * as browser from "../src/browser.js";
|
||||
import * as node from "../src/node.js";
|
||||
import { Sodium as BrowserSodium } from "../src/browser.ts";
|
||||
import { Sodium as NodeSodium } from "../src/node.ts";
|
||||
import { base64_variants } from "../src/types.ts";
|
||||
import { test } from "vitest";
|
||||
import {
|
||||
decrypt,
|
||||
@@ -27,7 +28,10 @@ import {
|
||||
hash,
|
||||
streamingDecrypt,
|
||||
streamingEncrypt
|
||||
} from "./utils.js";
|
||||
} from "./utils.ts";
|
||||
|
||||
const browser = new BrowserSodium();
|
||||
const node = new NodeSodium();
|
||||
|
||||
test("secretstream tags should be equal on node & browser variants", async (t) => {
|
||||
t.expect(browser.crypto_secretstream_xchacha20poly1305_TAG_FINAL).toBe(
|
||||
@@ -100,19 +104,19 @@ test("node & browser variants of base64 should be compatible", async (t) => {
|
||||
|
||||
t.expect(browser.to_base64(text)).toBe(node.to_base64(text));
|
||||
|
||||
t.expect(browser.to_base64(text, browser.base64_variants.ORIGINAL)).toBe(
|
||||
node.to_base64(text, node.base64_variants.ORIGINAL)
|
||||
t.expect(browser.to_base64(text, base64_variants.ORIGINAL)).toBe(
|
||||
node.to_base64(text, base64_variants.ORIGINAL)
|
||||
);
|
||||
|
||||
t.expect(
|
||||
browser.to_base64(text, browser.base64_variants.ORIGINAL_NO_PADDING)
|
||||
).toBe(node.to_base64(text, node.base64_variants.ORIGINAL_NO_PADDING));
|
||||
t.expect(browser.to_base64(text, base64_variants.ORIGINAL_NO_PADDING)).toBe(
|
||||
node.to_base64(text, base64_variants.ORIGINAL_NO_PADDING)
|
||||
);
|
||||
|
||||
t.expect(
|
||||
browser.to_base64(text, browser.base64_variants.URLSAFE_NO_PADDING)
|
||||
).toBe(node.to_base64(text, node.base64_variants.URLSAFE_NO_PADDING));
|
||||
t.expect(browser.to_base64(text, base64_variants.URLSAFE_NO_PADDING)).toBe(
|
||||
node.to_base64(text, base64_variants.URLSAFE_NO_PADDING)
|
||||
);
|
||||
|
||||
t.expect(browser.to_base64(text, browser.base64_variants.URLSAFE)).toBe(
|
||||
node.to_base64(text, node.base64_variants.URLSAFE)
|
||||
t.expect(browser.to_base64(text, base64_variants.URLSAFE)).toBe(
|
||||
node.to_base64(text, base64_variants.URLSAFE)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -16,13 +16,12 @@ 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 * as browser from "../src/browser.js";
|
||||
import * as node from "../src/node.js";
|
||||
// import * as browser from "../src/browser.js";
|
||||
// import * as node from "../src/node.js";
|
||||
|
||||
export async function streamingEncrypt(
|
||||
crypto: typeof node | typeof browser,
|
||||
key: Uint8Array
|
||||
) {
|
||||
import { ISodium } from "../src/types";
|
||||
|
||||
export async function streamingEncrypt(crypto: ISodium, key: Uint8Array) {
|
||||
await crypto.initialize();
|
||||
const { state, header } =
|
||||
crypto.crypto_secretstream_xchacha20poly1305_init_push(key, "base64");
|
||||
@@ -56,7 +55,7 @@ export async function streamingEncrypt(
|
||||
}
|
||||
|
||||
export async function streamingDecrypt(
|
||||
crypto: typeof node | typeof browser,
|
||||
crypto: ISodium,
|
||||
key: Uint8Array,
|
||||
cipher: { header: string; chunks: string[] }
|
||||
) {
|
||||
@@ -88,7 +87,7 @@ export async function streamingDecrypt(
|
||||
}
|
||||
|
||||
export async function decrypt(
|
||||
crypto: typeof node | typeof browser,
|
||||
crypto: ISodium,
|
||||
cipher: Uint8Array,
|
||||
nonce: Uint8Array,
|
||||
key: Uint8Array
|
||||
@@ -105,7 +104,7 @@ export async function decrypt(
|
||||
}
|
||||
|
||||
export async function encrypt(
|
||||
crypto: typeof node | typeof browser,
|
||||
crypto: ISodium,
|
||||
nonce: Uint8Array,
|
||||
key: Uint8Array
|
||||
) {
|
||||
@@ -120,7 +119,7 @@ export async function encrypt(
|
||||
);
|
||||
}
|
||||
|
||||
export async function getKey(crypto: typeof node | typeof browser) {
|
||||
export async function getKey(crypto: ISodium) {
|
||||
await crypto.initialize();
|
||||
|
||||
const saltBytes: Uint8Array = crypto.randombytes_buf(
|
||||
@@ -137,10 +136,10 @@ export async function getKey(crypto: typeof node | typeof browser) {
|
||||
return { key, salt: saltBytes };
|
||||
}
|
||||
|
||||
export async function hash(crypto: typeof node | typeof browser) {
|
||||
export async function hash(crypto: ISodium) {
|
||||
await crypto.initialize();
|
||||
const saltBytes = crypto.crypto_generichash(
|
||||
node.crypto_pwhash_SALTBYTES,
|
||||
crypto.crypto_pwhash_SALTBYTES,
|
||||
"mysalt"
|
||||
);
|
||||
return crypto.crypto_pwhash(
|
||||
@@ -149,7 +148,7 @@ export async function hash(crypto: typeof node | typeof browser) {
|
||||
saltBytes,
|
||||
3, // operations limit
|
||||
1024 * 1024 * 64, // memory limit (8MB)
|
||||
browser.crypto_pwhash_ALG_ARGON2ID13,
|
||||
crypto.crypto_pwhash_ALG_ARGON2ID13,
|
||||
"base64"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user