Skip to content

calldata public key verification work in client - #412

Draft
CedarMist wants to merge 1 commit into
mainfrom
CedarMist/cdpk-verification-munacl
Draft

calldata public key verification work in client#412
CedarMist wants to merge 1 commit into
mainfrom
CedarMist/cdpk-verification-munacl

Conversation

@CedarMist

Copy link
Copy Markdown
Contributor

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
@netlify

netlify Bot commented Sep 24, 2024

Copy link
Copy Markdown

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

HarryR commented Oct 21, 2024

Copy link
Copy Markdown

@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

lukaw3d commented Oct 22, 2024

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Contributor 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

kostko commented Oct 22, 2024

Copy link
Copy Markdown
Member

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
@matevz matevz assigned ZigaMr and unassigned CedarMist May 14, 2025
@matevz matevz removed this from the clients-js-2.1.0 milestone May 14, 2025
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.

6 participants