{"record":{"id":"1dd285ab660ac531","repo":"schollz/croc","slug":"sender-provided-an-invalid-peerpake-b2-bytelengt","errorCode":null,"errorMessage":"Sender provided an invalid ${peerPake.b2.byteLength}-byte PAKE salt","messagePattern":"Sender provided an invalid (.+?)-byte PAKE salt","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/protocol/client.ts","lineNumber":690,"sourceCode":"      textEncoder.encode(passphrase),\n      0,\n      curve,\n      PAKE_PURPOSE_TRANSFER,\n      room,\n    );\n    await sendControl(control, {\n      t: \"pake\",\n      v: PAKE_PROTOCOL_VERSION,\n      b: pake.bytes,\n      b2: textEncoder.encode(curve),\n    });\n    const peerPake = await receiveControl(control);\n    if (peerPake.t !== \"pake\" || !peerPake.b || !peerPake.b2) {\n      throw new Error(\"Sender did not complete the croc PAKE handshake\");\n    }\n    requirePakeVersion(peerPake.v);\n    if (peerPake.b2.byteLength !== PAKE_SALT_SIZE) {\n      throw new Error(`Sender provided an invalid ${peerPake.b2.byteLength}-byte PAKE salt`);\n    }\n    const finished = await wasm().pakeUpdate(pake.handle, peerPake.b);\n    const peerKeys = await wasm().derivePeerKeys(\n      finished.key,\n      peerPake.b2,\n      PAKE_PURPOSE_TRANSFER,\n      room,\n      curve,\n      pake.bytes,\n      peerPake.b,\n    );\n    await sendControl(control, {\n      t: \"pake-confirm\",\n      v: PAKE_PROTOCOL_VERSION,\n      b: peerKeys.confirmationA,\n    });\n    const confirmationB = await receiveControl(control);\n    if (confirmationB.t !== \"pake-confirm\" || !confirmationB.b) {","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/schollz/croc/blob/e25f1bdc04f07f094d50b0a1bf67e2563944b57a/web/src/protocol/client.ts#L672-L708","documentation":"Thrown by the recipient when the sender's pake reply carries a b2 (salt) field whose byte length is not exactly 32 (PAKE_SALT_SIZE). The salt feeds derivePeerKeys, so a wrong-length salt means key derivation would diverge from the sender's; the recipient rejects it rather than derive mismatched keys. The message includes the offending length to aid diagnosis.","triggerScenarios":"Peer sends a pake message where b2 is the curve name text (as the recipient's own initial message uses b2 for the curve) instead of the salt — a role confusion in a custom sender; truncated or garbage b2 from an incompatible client; salt generated with a different size constant in a fork.","commonSituations":"Interoperating with the croc CLI or a fork where b2 semantics differ per direction; version skew after PAKE_PROTOCOL_VERSION changed salt handling; a hand-rolled sender that copies the recipient's message shape (v, b, b2=curve) instead of replying with (v, b, b2=salt).","solutions":["Align both peers on PAKE_PROTOCOL_VERSION 2 semantics: sender replies with b=PAKE bytes, b2=32-byte random salt","Upgrade both sides so salt size constants match (PAKE_SALT_SIZE = 32)","When writing a sender implementation, do not mirror the recipient's pake message layout — the b2 field has a different meaning in each direction","Check requirePakeVersion passes first; an old-version peer may slip through with a different salt format if version negotiation is bypassed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Sender-side pre-flight: generate the salt with the agreed size before replying\nconst PAKE_SALT_SIZE = 32;\nconst salt = randomBytes(PAKE_SALT_SIZE);\nif (salt.byteLength !== PAKE_SALT_SIZE) throw new Error(\"salt generation mismatch\");","typeGuard":"function isValidPakeSalt(b2: Uint8Array | undefined): b2 is Uint8Array {\n  return !!b2 && b2.byteLength === 32;\n}","tryCatchPattern":"catch (e) {\n  if (e instanceof Error && /-byte PAKE salt$/.test(e.message)) {\n    // peer sent a wrong-shaped pake reply (role confusion or version skew): upgrade both peers\n  }\n  throw e;\n}","preventionTips":["Remember b2 means curve name in the recipient's initial pake but salt in the sender's reply — do not mirror messages","Pin both peers to the same PAKE_PROTOCOL_VERSION and salt size","Fuzz-test your sender against the recipient's checks (type, b, b2 length, version) before shipping"],"tags":["pake","handshake","validation","security"],"backgroundTag":null,"analyzedSha":"e25f1bdc04f07f094d50b0a1bf67e2563944b57a","analyzedAt":"2026-08-15T12:53:39.096Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}