Binding

What two CoinCards prove to each other, what that permits, and what it does not yet do.

The short answer. Binding is mutual proof of possession: each card signs a fresh nonce supplied by the other, so each side learns that the other controls the private key for the public key it claims. It is not a shared secret and not an encrypted channel. Those are the next step, and this page is explicit about the difference.

What exists today

StepWho actsWhat is produced
1 · connecteither party A room. Both accounts are in it; who is who is recorded.
2 · directioneach party intent = send or get. Opposite intents are what make a transfer legal.
3 · nonceseach party A 32-byte random nonce per side, stored against the connection.
4 · signeach card Card A signs B's nonce; card B signs A's nonce. Signatures are ECDSA over SHA-256, produced on the chip.
5 · verifyservice Each signature is checked against the card public key on file for that account. Both verified ⇒ mutual: true.

Once mutual is true the service records that this pair of cards proved each other. What it is then used for is a policy decision, not a cryptographic one: it is what distinguishes a transfer to a known, proved counterparty from a transfer to an arbitrary recipient.

What binding does not provide

What it does buy you

PropertyWhy it follows
A card cannot be impersonated in a binding The signature only verifies under the key enrolled for that account, and the key never leaves the chip.
A binding cannot be replayed Nonces are random and single-use; a captured signature does not verify against a new nonce.
A transfer has a proved counterparty The receiving card signs before value moves, so "who is on the other end" is answered by the chip rather than by a handle typed into a field.
The tunnel/custody choice is informed Card-to-card transfer requires mutual proof; without it, value moves under custody and is recorded.

Where the channel becomes real

Both cards already hold P-256 keys, so a genuine pair-wise channel needs one extra step at bind time:

shared   = ECDH(myCardKey, theirCardKey)          // same on both sides, unknown elsewhere
key      = HKDF-SHA256(shared, salt = nonceA||nonceB, info = "coincard-channel-v1")
payload  = AEAD-Seal(key, token64, nonce = random 12 bytes)

Requirements that make this worth doing rather than decorative:

Status. Implemented: nonces, card signatures, verification, and the policy use of mutual. Not implemented: key agreement, message encryption, payload chaining. Until those exist, card-to-card transfer of a token's payload is a design, and a send moves value under escrow custody — which is recorded, reversible only by redemption, and visible in the issuer's ledger.

Why this matters to a bank

The separation is what makes the mechanism auditable. A binding is evidence — a signature a chip produced over a value nobody could predict — and evidence can be stored, re-checked and disputed. A shared key is a secret, and a secret nobody can inspect is a promise. CoinCard keeps the first for its records and only introduces the second where confidentiality of the payload is genuinely required.

Sandbox deployment, USD, English. Values shown elsewhere in the system are test values and are not money. This page describes implemented behaviour; the section on the encrypted channel describes intent and is labelled as such.