This is the main library to handle Vaultys DID and handcheck protocol
4.0.0 is an intentionally breaking security release. Identity ids, DIDs and secrets are unchanged, but the protocols below are not compatible with 3.x and older:
- Handshake (Challenger): only challenge
version = 1exists; v0 encoding and v0 signatures are removed and any other version is rejected. Signatures aresign(SHA-256("VAULTYS_HANDSHAKE_V1" || unsignedBytes))through the handshake-onlysignHandshake/verifyHandshake. Strict state machine: a responder only accepts an INIT, an initiator only a STEP1 matching exactly what it sent, a responder only a COMPLETE matching exactly its STEP1 (no more signing a STEP1 it never initiated, no replayed COMPLETE, no reflection).setChallenge/fromCertificateare read-only.createChallenge(protocol, service, metadata?)lost itsversionargument andIdManager.protocol_version/setProtocolVersionare gone. Accept callbacks receive the remote identity and accept flows require an INIT as first message. - Signature domains:
signChallengekeepsVAULTYS_SIGN; the new publicVaultysId.sign/verifyuseVAULTYS_RAW. No public API can produce a handshake signature anymore. - DHIES v2 replaces DHIES: sender-authenticated (
es || ss),0x02 || nonce || e_pk || secretbox; old ciphertexts can't be decrypted. - IdManager persistence: the store always keeps the full secret (
store.secret); stores/backups restore the exact same identity (algorithm, type, DID). Entropy-only (legacy) stores are rejected; restore them explicitly withnew IdManager(await VaultysId.fromEntropy(entropy, type, alg), store). Empty backup passphrases are rejected. - Default deny for remote services:
acceptPRF,acceptDecryptFile/acceptEncryptFile,acceptDecryptandacceptSignFilerefuse unless anacceptcallback approves the remote. The file-encryption PRF namespace (encryption/...) is never served throughacceptPRFto another identity. - WebAuthn: no silent fallback to the insecure
SoftCredentialsauthenticator; callenableSoftCredentials()explicitly (tests only). Assertions requiretype === "webauthn.get"and the UP flag, and check rpId/origin when configured withconfigureWebAuthn({ rpId, origin }). FIDO2 Dilithium5 keys are parsed correctly. - OTP:
await me.getOTP(contact, prefix?, timelock?, time?)is nowHMAC-SHA256(SHA-256(X25519(my cypher sk, contact cypher pk)), prefix || certificate || uint64be(counter)), so only the two parties can compute it. - requestConnect / acceptConnect are now a plain
p2p/authhandshake (optionally pinned to a DID) saving the contact. - Untrusted ids, secrets and certificates are length-checked and never throw uncaught
TypeErrors;VaultysId.decryptcorrectly parses a hex sender id.
Cross-language vectors: test/interops/security-v2-vectors.json (npx tsx test/interops/generate-security-v2-vectors.ts).
- install nodejs (20.x recommended) and pnpm (https://pnpm.io/fr/installation)
- checkout this repo
- install dependencies:
pnpm i - compile for web
pnpm build_webor for nodepnpm build - run test
pnpm test
The repository also have some examples. Try them:
pnpx tsx example/sideChannelAttack.jspnpx tsx example/logChallenge.js