Skip to content

feat(bridge): prove the token with an HMAC challenge instead of sending it - #31

Merged
AlxcBTW merged 2 commits into
mainfrom
feat/bridge-hmac-hello
Oct 27, 2026
Merged

AlxcBTW merged 2 commits into
mainfrom
feat/bridge-hmac-hello

Conversation

@AlxcBTW

@AlxcBTW AlxcBTW commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

What

The bridge no longer sends the per-launch token in hello. Protocol version 1 (anyplaynet/network ADR 0039, spec/bridge-protocol.md#authentication): the bridge sends a fresh 32-byte nonce, the net service answers with its own nonce and its proof, the bridge verifies that proof before it answers with its own, and the net service then sends welcome or reject. Proofs are HMAC-SHA-256 keyed with the token over AnyPlay bridge v1, a role byte and both nonces, compared in constant time. Handshake frames are limited to 1024 bytes of payload. SHA-256 and HMAC are a header (NetBridgeAuth.hpp), nonces come from BCryptGenRandom or /dev/urandom.

A bridge that cannot get random numbers, or that meets a service that cannot prove the token, closes the connection and sends nothing. An old net service rejects the new hello and an old bridge gets a reject naming both versions from the new service; the launcher ships both together.

The network side is anyplaynet/network#125; it merges only after this builds green on Windows.

Tested

Not tested on a game. The tests: net_bridge_auth_vectors (SHA-256 and RFC 4231 vectors, the spec's proof vectors, same bytes as the Rust side), net_bridge_auth_impostor (a fake service that proves with another token never gets an auth frame; the token is in no frame the bridge sends), and the existing FakeNetService tests now run the full handshake. tools/check_conventions.py passes locally; sources syntax-checked with g++. CI builds are the first full build.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

…ng it

Protocol version 1: hello carries a fresh nonce, the net service answers with
its nonce and its proof, the bridge verifies it before sending its own proof.
Proofs are HMAC-SHA-256 over a context string, the role and both nonces,
compared in constant time. Frames carry at most 1024 bytes until welcome.
@AlxcBTW
AlxcBTW merged commit b1ac222 into main Oct 27, 2026
8 checks passed
AlxcBTW added a commit that referenced this pull request Oct 28, 2026
… protocol 1 (#45)

network.ref still pinned f65d3a8, from before bridge protocol 1 (network#125). Since #31 the bridge proves its token with the HMAC hello, which that service rejects ("token does not match this game start"), so bridge-e2e failed on main and on every PR. Pin network main 16774aa.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant