Wire Argon2id through crypto provider, rebuild WASM with Rust binding

wallet-encryption.js was importing argon2id directly from @noble/hashes,
  bypassing the crypto provider entirely and always using the slow pure-JS
  implementation. Now routes through the provider so WASM (Rust) and JSI
  (native) backends are used when available, with Noble as a last-resort
  JS fallback that emits a console.warn.
This commit is contained in:
Matt Hess
2026-02-10 19:28:12 +00:00
parent 293e6f6b96
commit 530b3ad3c9
7 changed files with 51 additions and 3 deletions
+29
View File
@@ -331,6 +331,35 @@ pub fn sha256(data: &[u8]) -> Vec<u8> {
hasher.finalize().to_vec()
}
/// Argon2id key derivation (WASM-accessible).
/// password, salt: arbitrary-length byte slices.
/// t_cost: number of iterations, m_cost: memory in KiB, parallelism: threads.
/// dk_len: desired output length in bytes.
/// Returns the derived key bytes, or empty vec on error.
#[wasm_bindgen]
pub fn argon2id_hash(
password: &[u8],
salt: &[u8],
t_cost: u32,
m_cost: u32,
parallelism: u32,
dk_len: u32,
) -> Vec<u8> {
use argon2::{Argon2, Algorithm, Version, Params};
let params = match Params::new(m_cost, t_cost, parallelism, Some(dk_len as usize)) {
Ok(p) => p,
Err(_) => return Vec::new(),
};
let argon2 = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
let mut out = vec![0u8; dk_len as usize];
match argon2.hash_password_into(password, salt, &mut out) {
Ok(_) => out,
Err(_) => Vec::new(),
}
}
/// Verify a signature against a DER-encoded SubjectPublicKeyInfo (SPKI) key.
///
/// Supports:
+7
View File
@@ -10,6 +10,7 @@
import { keccak256 as jsKeccak } from '../keccak.js';
import { blake2b as jsBlake2b } from '../blake2b.js';
import { sha256 as nobleSha256 } from '@noble/hashes/sha2.js';
import { argon2id as nobleArgon2id } from '@noble/hashes/argon2.js';
import {
scAdd, scSub, scMul, scMulAdd, scMulSub,
scReduce32, scReduce64, scInvert, scCheck, scIsZero
@@ -90,6 +91,12 @@ export class JsCryptoBackend {
// Oracle signature verification
sha256(data) { return nobleSha256(data); }
// Argon2id key derivation (JS fallback via Noble — slow, use WASM/JSI when possible)
argon2id(password, salt, opts) {
console.warn('[salvium-js] suboptimal crypto path: js->argon2id (call initCrypto() for WASM acceleration)');
return nobleArgon2id(password, salt, opts);
}
/**
* Verify signature using WebCrypto (browser/Node.js 15+) or Node.js crypto.
* @param {Uint8Array} message - Message bytes (will be SHA-256 hashed)
+2 -2
View File
@@ -188,8 +188,8 @@ export class JsiCryptoBackend {
// ─── Key Derivation ─────────────────────────────────────────────────────
async argon2id(password, salt, tCost, mCost, parallelism, outLen) {
return this.native.argon2id(password, salt, tCost, mCost, parallelism, outLen);
argon2id(password, salt, opts) {
return this.native.argon2id(password, salt, opts.t, opts.m, opts.p, opts.dkLen);
}
}
+7
View File
@@ -222,6 +222,13 @@ export class WasmCryptoBackend {
// Oracle signature verification
sha256(data) { return nobleSha256(data); }
// Argon2id key derivation via Rust/WASM
argon2id(password, salt, opts) {
const result = this.wasm.argon2id_hash(password, salt, opts.t, opts.m, opts.p, opts.dkLen);
if (result.length === 0) throw new Error('Argon2id failed');
return result;
}
async verifySignature(message, signature, pubkeyDer) {
// WASM can't do ECDSA/DSA verification (native-only crates).
// Use WebCrypto (browser/Node 15+) or Node.js crypto as fallback.
+2
View File
@@ -39,6 +39,8 @@ export {
commit, zeroCommit, genCommitmentMask,
// Oracle signature verification
sha256, verifySignature,
// Key derivation
argon2id,
// CARROT key derivation
computeCarrotSpendPubkey, computeCarrotAccountViewPubkey,
computeCarrotMainAddressViewPubkey,
+3
View File
@@ -133,6 +133,9 @@ export async function verifySignature(message, signature, pubkeyDer) {
return getCryptoBackend().verifySignature(message, signature, pubkeyDer);
}
// Key derivation
export function argon2id(password, salt, opts) { return getCryptoBackend().argon2id(password, salt, opts); }
// =============================================================================
// Composite functions — built on top of backend primitives
// =============================================================================
+1 -1
View File
@@ -17,9 +17,9 @@
import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';
import { gcm } from '@noble/ciphers/aes.js';
import { argon2id } from '@noble/hashes/argon2.js';
import { hkdf } from '@noble/hashes/hkdf.js';
import { sha256 } from '@noble/hashes/sha2.js';
import { argon2id } from './crypto/index.js';
import { randomBytes, concatBytes, utf8ToBytes } from '@noble/hashes/utils.js';
import { bytesToHex, hexToBytes } from './address.js';