Most, if not all, wallets implementing the FIO Protocol, are relying on a single API node (typically ran by a BP). This creates an attack vector, where an attacker can hijack the API node or any device along the route from wallet to API node and return their own response, For example:
Attacker can return their own public address in get_pub_address response, as this response is stored/returned open-text.
Attacker could substitute FIO Request content with their own including creating a new encrypted blob. Because the wallet has no idea which FIO Public Key should own the Payee FIO Address, an attacker could use a different private/public key pair to encrypt the new blob.
Even though the risk applies to any information returned by the API, the primary concern is around the information which is used by wallet to execute a transfer of value on another chain, specifically:
Public Address Mapping
Pending FIO Request
Querying multiple nodes with key validation
API node operators, primarily BPs, will publish their API end-points along with public keys used to sign the Critical Information.
The wallet developer will manually validate API end-points and hard-code them into their wallet along with their corresponding public keys. Wallet developer would regularly update this list with new software releases.
When wallet’s user wants to access Critical Information, e.g. resolve FIO Address to public address on BTC blockchain, the wallet would randomly select X API endpoints and send parallel queries to each.
The API node would look-up the data, sign it using their private key, and return.
The wallet would verify the signature using hard-coded public key and compare responses received. If Y responses matched, the information would be presented t otherwise it would not.
Questions and other considerations
What should X and Y be, especially given the fact that the hard-coded data can not be changed on the fly?
Should the wallet handle no response (e.g. server down) differently than invalid response?
We have considered an approach where the known API end-points could be queried for other know API end-point in order to prevent a situation where majority of know API end-points were replaced, but decided against it due to increased complexity and nominal value. An argument has been made that if majority of nodes have been replaced, a manual update of the known endpoints is beneficial.
This approach does not give mathematical certainty to the wallet that the information is accurate
It also has a boot-strapping problem. How do you get the initial API nodes and keys to the wallet. Is it Github page? If so what if that gets hacked?
SELECTED: Verify block signature
The wallet developer would hard-code a list of know block producers and would regularly update this list with new software releases.
API nodes would allow for easy retrieval of block producer schedule updates providing block in which it occurred and blocks where other BPs sign it.
The wallet would automatically query a single API end-point to receive a list of block producer schedule updates. It would then fetch the corresponding block and its transactions and:
Verify that the block was signed by 2/3+1 of known producers.
Add any new producers to list of known producers.
API nodes ran by BPs would be published on chain.
When wallet’s user wants to access Critical Information, e.g. resolve FIO Address to public address on BTC blockchain, the wallet would send API query to 2/3+1 BP API nodes.
The API node would look-up the data, and return it signed with their signing key.