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.
|
// distributed per recipient via crypto_box envelopes.
|
||||||
secretbox(plaintext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
|
secretbox(plaintext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
|
||||||
secretboxOpen(ciphertext: 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;
|
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),
|
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),
|
secretbox: (m, n, k) => sodium.crypto_secretbox_easy(m, n, k),
|
||||||
secretboxOpen: (c, n, k) => sodium.crypto_secretbox_open_easy(c, 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