Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

calldata public key verification work in client #412

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

CedarMist
Copy link
Member

No description provided.

@CedarMist CedarMist added the blocked Pull requests that are blocked by another issue label Sep 24, 2024
@CedarMist CedarMist added this to the clients-js-2.1.0 milestone Sep 24, 2024
@CedarMist CedarMist self-assigned this Sep 24, 2024
Copy link

netlify bot commented Sep 24, 2024

Deploy Preview for oasisprotocol-sapphire-paratime canceled.

Name Link
🔨 Latest commit ef0dcbc
🔍 Latest deploy log https://app.netlify.com/sites/oasisprotocol-sapphire-paratime/deploys/671d406a16a125000811342c

@HarryR
Copy link

HarryR commented Oct 21, 2024

@matevz @kostko

Re: calldata public key verification in clients

To prevent RPC server MITM.

This applies to all clients where you want to establish secure connection between a client app & Sapphire, without having to run your own RPC node.

Signature is in the form of Sign(sk, (key || checksum || runtime id || key pair id || epoch || expiration epoch)), meaning we need to have checksum, runtime id and key pair id.

There are a couple of approaches which were considered:

  1. Hard-code Keymanager public key in client, to verify result of oasis_callDataPublicKey and core.CallDataPublicKey
  2. Build light client
  3. Have smart contract on-chain generate long-term key pair, use together with core.CallDataPublicKey to establish trust
  4. Serve key manager info from a HTTPS URL

Approach 1

How frequently would checksum, sk and key pair id need to change?

If sk is rotated, or checksum changes or key pair id changes - client will reject new signed CallDataPublicKeys

This would break previously deployed dApps if key is rotated.

Approach 2

This would add significant weight to every client, probably megabytes or more, and may take a fair amount of time to sync every time you start a dApp.

This would be difficult in environments where outbound connections are firewalled etc.

Consensus upgrades could break previously deployed dApps if protocol or light client becomes incompatible.

Approach 3

If key manager signing key changes the smart contract will continue signing stuff without interruption, so the key manager key can rotate etc.

But, the root of trust is a key inside a smart contract on Sapphire which is embedded into the client library.

This would require compromise of Sapphire compute node to extract the key before a MITM attack can be made.

Approach 4

Requires an outbound HTTPS connection to a domain to retrieve the key information. This would be per-chain? (e.g. Localnet, Testnet, Mainnet, Pontus-[Local/Test/Main/Dev].

Using a static URL to retrieve the key depending on Chain ID is particularly difficult with Localnet, which may not be at localhost:8545 (e.g. if it's deployed with docker swarm).

@lukaw3d
Copy link
Member

lukaw3d commented Oct 22, 2024

Potential approach 5:

  • Make an encrypted test transaction
  • If it succeeds there is no MITM

If MITM returns a fake public key and reads and submits your transaction: invalid encryption envelope
If MITM returns a fake public key and rewrites your transaction using real public key: invalid signature

i think

@CedarMist
Copy link
Member Author

Yup, if the RPC does MITM your tx will either fail with decryption error or will be signed by a different key (so different tx hash).

This approach requires you to spend gas though, every time an app is loaded. Which will require signing from a gas paying account

@kostko
Copy link
Member

kostko commented Oct 22, 2024

I assume it could also be a combination of things that one can use, as long as the app developer can decide what tradeoff to use.

A note about light clients:

  • It should be relatively fast to sync a light client when using bisection. You can also cache intermediate verified headers (just a known trusted height and header hash is enough) in local storage to make things even faster next time. Similar to what our runtimes are also doing, since they also need to do light client verification all the time.
  • Light clients should be fairly resistant even to breaking changes in consensus layer logic as they don't re-execute logic, just verify headers to derive the state roots. The only thing where the clients could break is if the consensus state representation changes in an incompatible way. But we can make sure this does not happen and give enough time for the clients to upgrade when it does.
  • The only concern is the size of the light client code. But someone should verify this. It should be possible to compile a simple Rust light client to WASM and see how much we can optimize that. All the building blocks are already there.

@CedarMist CedarMist force-pushed the CedarMist/cdpk-verification-munacl branch from fd3d8a5 to ef0dcbc Compare October 26, 2024 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Pull requests that are blocked by another issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants