Madeleine Charity
|Sep 5, 2024
Yesterday, we launched a new SDK that allows developers to connect any application to a Privy wallet using RainbowKit. We could not be more excited about this feature. Cross-app wallets will enable teams to bring one of crypto's most powerful features—interoperability—to mainstream audiences. In just a few minutes, developers can add the Privy connector to their wagmi configuration and seamlessly connect to a Privy provider wallet. This blog post takes you behind the scenes to understand how we built this powerful feature.
At the core of this experience is Mobile Wallet Protocol (MWP), which allows external applications to securely interface with a wallet. Security is always our priority at Privy and as a hardened standard, we can leverage its security and compatibility to bring cross-app wallets to a broader audience.
The protocol is a two step process; first the wallet and the external application connect and agree on a shared secret. The connect step leverages a cryptographic system called Diffie Hellman key exchange. Diffie Hellman allows two parties to securely generate the same shared secret with one party's private key and the other's public key.
Then, the external application encrypts requests with this shared secret and sends them to the wallet to transact. The wallet only acts on these requests if they were encrypted with the shared secret generated in the connect step. As always, the user must approve the transaction, after which an encrypted response is sent back.
Let's look deeper into these two steps. Note that below, I will refer to the external application as the requester app and the wallet it wants to connect to as the Privy provider app.
The requester app initiates the connection. First, it generates a requesterPublicKey
and requesterPrivateKey
pair and sends the requesterPublicKey
to the provider app. In our SDK, this pops up the /cross-app/connect page on the provider app with the requesterPublicKey
and the providerAppId
.
The provider application prompts the user to approve or deny the connection. On approval, the provider generates a providerPublicKey
and providerPrivateKey
pair and uses its providerPrivateKey
key and the requesterPublicKey
to recover the sharedSecret
. The provider stores this sharedSecret
in the browser, along with the requesterPublicKey
. Then it sends the providerPublicKey
it generated back to the requester app and closes the popup.
The requester application uses the providerPublicKey
and its own requesterPrivateKey
to generate the same sharedSecret
. It stores this sharedSecret
and its own requesterPublicKey
in the browser.
Now, the requester and provider application both have the same sharedSecret stored in the browser. When the requester application wants to use the provider’s wallet, it encrypts the request using the sharedSecret
.
The requester application encrypts its request using the sharedSecret
and sends the encryptedRequest
, along with the requesterPublicKey
, to the provider application. In our SDK, this pops up the /cross-app/transact page on the provider application.
The provider matches the requesterPublicKey
and requester origin to the values stored during the connect step and then decrypts the request using the sharedSecret
. Only requests encrypted with the sharedSecret
generated in the connect step will be allowed to continue. Once the user approves the request, the provider wallet fulfills the request, encrypts the result, and sends the encryptedResult
back to the requester.
The requester uses the sharedSecret
to decrypt and get the result. The requester application has now transacted with the Privy provided wallet!
To learn more, check out our docs and a demo app we built to showcase the connector. We are so excited to see what you build on cross app wallets!