Signatures
All signature variants expose the same surface: keypair(), sign(), verify(), buffer_to_string() — typed as IFnDsa (types ship with the package; no @types/… install).
:::note SQIsign performance Level 1 signing can take seconds (or longer) depending on hardware. Prefer sign-once, verify-many for certificates and firmware-style use. :::
Node.js / backend
import {
loadSqisignLvl1,
loadSqisignLvl5,
loadFnDsa512,
type IFnDsa,
} from "quantum-resistant-rustykey";
async function demo(): Promise<void> {
const message: Uint8Array = new TextEncoder().encode("RustyKey signature test");
const variants: ReadonlyArray<readonly [string, IFnDsa]> = [
["SQIsign-I", await loadSqisignLvl1()],
["SQIsign-V", await loadSqisignLvl5()],
["FN-DSA-512", await loadFnDsa512()],
];
for (const [name, signer] of variants) {
const kp = signer.keypair();
const pk: Uint8Array = await kp.get("public_key");
const sk: Uint8Array = await kp.get("private_key");
const sig: Uint8Array = await signer.sign(message, sk);
const ok: boolean = await signer.verify(sig, message, pk);
console.log(`${name}:`, ok ? "OK" : "FAIL");
}
}
demo().catch(console.error);
Browser
Browser load*().keypair() / .sign() throw. Keygen and sign go through the OPFS encrypted-sk wallet (WebAuthn UV + PRF, ciphertext at rest). verify() can still use the standard loaders.
import {
loadOpfsSkWallet,
loadSqisignLvl1,
opfsSkTriggerWebAuthn,
setOpfsSkWorkerUrl,
OPFS_SK_SLOT_SD_BUNDLE,
} from "quantum-resistant-rustykey";
setOpfsSkWorkerUrl("/pqc/opfs-sk-worker.js");
const { prf } = await opfsSkTriggerWebAuthn({
mode: "get",
publicKey: authenticationOptions, // RP options used prf: {}
salt,
});
const wallet = await loadOpfsSkWallet();
const { public_key } = await wallet.keygen("sqisign-lvl1", prf, {
slot: OPFS_SK_SLOT_SD_BUNDLE,
});
const message = new TextEncoder().encode("hello from browser signatures");
const signature = await wallet.sign("sqisign-lvl1", message, prf, {
slot: OPFS_SK_SLOT_SD_BUNDLE,
});
const sq = await loadSqisignLvl1();
const ok = await sq.verify(signature, message, public_key);
Web app security notes
- Never store private keys in
localStorage/sessionStorage - Prefer HTTPS and short-lived keys
- Browser private keys stay AES-GCM ciphertext in OPFS; unwrap only inside the wallet worker after WebAuthn UV + PRF
Also see SLH-DSA and SQIsign-webGPU.