feat(shared): extend CryptoBackend with pwhash + scalarMultBase
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { CryptoBackend } from './backend';
|
||||
import { makeWasmTestBackend } from './testBackend';
|
||||
|
||||
describe('CryptoBackend contract — extended (pwhash + scalarMultBase)', () => {
|
||||
it('pwhashConsts exposes the constants userKey.ts needs', async () => {
|
||||
const backend: CryptoBackend = await makeWasmTestBackend();
|
||||
expect(backend.pwhashConsts.OPSLIMIT_MODERATE).toBeGreaterThan(0);
|
||||
expect(backend.pwhashConsts.MEMLIMIT_MODERATE).toBeGreaterThan(0);
|
||||
expect(backend.pwhashConsts.ALG_ARGON2ID13).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('pwhash is deterministic for fixed input + salt', async () => {
|
||||
const backend: CryptoBackend = await makeWasmTestBackend();
|
||||
const salt = new Uint8Array(16).fill(7);
|
||||
const a = backend.pwhash(
|
||||
32,
|
||||
'hunter2',
|
||||
salt,
|
||||
backend.pwhashConsts.OPSLIMIT_MODERATE,
|
||||
backend.pwhashConsts.MEMLIMIT_MODERATE,
|
||||
backend.pwhashConsts.ALG_ARGON2ID13,
|
||||
);
|
||||
const b = backend.pwhash(
|
||||
32,
|
||||
'hunter2',
|
||||
salt,
|
||||
backend.pwhashConsts.OPSLIMIT_MODERATE,
|
||||
backend.pwhashConsts.MEMLIMIT_MODERATE,
|
||||
backend.pwhashConsts.ALG_ARGON2ID13,
|
||||
);
|
||||
expect(a).toEqual(b);
|
||||
expect(a.length).toBe(32);
|
||||
});
|
||||
|
||||
it('scalarMultBase maps the private key of a generated keypair to its public key', async () => {
|
||||
const backend: CryptoBackend = await makeWasmTestBackend();
|
||||
const kp = backend.generateKeyPair();
|
||||
const derived = backend.scalarMultBase(kp.privateKey);
|
||||
expect(derived).toEqual(kp.publicKey);
|
||||
});
|
||||
});
|
||||
@@ -47,6 +47,30 @@ export interface CryptoBackend {
|
||||
// distributed per recipient via crypto_box envelopes.
|
||||
secretbox(plaintext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
|
||||
secretboxOpen(ciphertext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Key derivation + public-key derivation. Added so the user-key flow
|
||||
// (Argon2id KDF, scalarmult-base for public-key derivation from a cached
|
||||
// private key) does not have to import libsodium-wrappers-sumo at module
|
||||
// top level — that import does not load in React Native's Hermes runtime.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
readonly pwhashConsts: {
|
||||
OPSLIMIT_MODERATE: number;
|
||||
MEMLIMIT_MODERATE: number;
|
||||
ALG_ARGON2ID13: number;
|
||||
};
|
||||
|
||||
pwhash(
|
||||
outLen: number,
|
||||
password: string,
|
||||
salt: Uint8Array,
|
||||
opslimit: number,
|
||||
memlimit: number,
|
||||
alg: number,
|
||||
): Uint8Array;
|
||||
|
||||
scalarMultBase(privateKey: Uint8Array): Uint8Array;
|
||||
}
|
||||
|
||||
let current: CryptoBackend | null = null;
|
||||
|
||||
@@ -22,5 +22,13 @@ export async function makeWasmTestBackend(): Promise<CryptoBackend> {
|
||||
boxOpen: (c, n, pk, sk) => sodium.crypto_box_open_easy(c, n, pk, sk),
|
||||
secretbox: (m, n, k) => sodium.crypto_secretbox_easy(m, n, k),
|
||||
secretboxOpen: (c, n, k) => sodium.crypto_secretbox_open_easy(c, n, k),
|
||||
pwhashConsts: {
|
||||
OPSLIMIT_MODERATE: sodium.crypto_pwhash_OPSLIMIT_MODERATE,
|
||||
MEMLIMIT_MODERATE: sodium.crypto_pwhash_MEMLIMIT_MODERATE,
|
||||
ALG_ARGON2ID13: sodium.crypto_pwhash_ALG_ARGON2ID13,
|
||||
},
|
||||
pwhash: (outLen, password, salt, opslimit, memlimit, alg) =>
|
||||
sodium.crypto_pwhash(outLen, password, salt, opslimit, memlimit, alg),
|
||||
scalarMultBase: (priv) => sodium.crypto_scalarmult_base(priv),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user