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:
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -39,6 +39,8 @@ export {
|
||||
commit, zeroCommit, genCommitmentMask,
|
||||
// Oracle signature verification
|
||||
sha256, verifySignature,
|
||||
// Key derivation
|
||||
argon2id,
|
||||
// CARROT key derivation
|
||||
computeCarrotSpendPubkey, computeCarrotAccountViewPubkey,
|
||||
computeCarrotMainAddressViewPubkey,
|
||||
|
||||
@@ -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
|
||||
// =============================================================================
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user