Integrating with the DeSo Identity on Mobile.
In the world of blockchain, user private keys are extremely sensitive information.
This is because, unlike Web2 password, private keys cannot be modified, which means that if somebody gets a hold of your private key, you're potentially forever vulnerable to an attack and there isn't much you can do unless you move your entire account to another private key.
We are firm believers that user primary keys should never be shared with third-party applications, regardless of their security practices, and so we created derived keys, which significantly lower attack vectors related to unauthorized access to user credentials.
Derived keys are impermanent and they usually automatically expire about 30 days after being issued.
Derived keys can also be de-authorized at any point, which we believe will allow for the creation of advanced security systems in the future that can mitigate the risks originating from key leakage.
Transaction Spending Limitblock height is reached, derived keys will need to be authorized to perform specific transaction types as well as more specific operations for Creator Coin, DAO Coin, and NFT transaction types.
Check out TransactionSpendingLimitResponse to learn how to construct the Transaction Spending Limit object.
A derived key is a pair of public and private cryptographic keys that are authorized to sign transactions on behalf of another key pair.
That is, if you hold a valid derived key of a user, you can submit a transaction signed by that derived key, and it will be regarded as a valid transaction as if it was made by that user.
This is particularly useful in mobile applications because it means you only have to interact with the DeSo Identity Service once, just to get the derived key of a user.
It also means that derived keys are extremely sensitive information and therefore should be handled in secure storage with the utmost caution, ideally by experienced software engineers.
The flow of using the derived keys is as follows:
- 2.Construct a
AuthorizeDerivedKeytransaction via Backend API through
- 3.Sign the
AuthorizeDerivedKeytransaction with the derived key
- 4.Submit signed
- 5.(Optional) Confirm that the derived key was successfully authorized through Backend API in
In case your application requires offline signing e.g. when you’re a mobile client, identity can accommodate you with derived key material.
const derive = window.open('https://identity.deso.org/derive?callback=...');
Once the user completes the identity flow, you’ll receive a response containing the derived keypair.
For simplicity, we list the response payload as a JSON object; however, you'll receive it as URL parameters in a callback.
Let’s take a look at these values:
accessSignatureis a proof of access, equal to an owner-signed digest of
sha256(derivedPublicKey + expirationBlock + transactionSpendingLimitBytes)(For more details check out the implementation)
derivedSeedHexis the derived keypair
expirationBlockis a future block height, and represents the expiration “date” (block) of the derived key. Derived keys expire after about 30 days. After that period, you will have to generate and authorize another derived key. To check if a derived key is valid you should compare the current block height, e.g. taken from
/api/v0/get-app-stateBackend API endpoint, with the
expirationBlockthat you can find by querying the
/api/v0/get-user-derived-keysBackend API endpoint.
derivedJwtis a JWT token with a month-long timeout signed by the
jwtis a JWT token with a month-long timeout signed by the owner
networkis the network for which this derived key was generated
messagingKeyNameis the key name used for v3 messaging
messagingKeySignatureis the key signature used for v3 messaging
messagingPublicKeyBase58Checkis the public key used for v3 messaging
messagingPrivateKeyis the private key used for v3 messaging
publicKeyBase58Checkis the public key that is the parent of this derived key.
transactionSpendingLimitHexis a hex string representing the TransactionSpendingLimit for this derived key.
Before any signing can happen, a derived key must first be activated by submitting an
authorizeDerivedKeytransaction, containing the
To make the transaction, make a request to the
/api/v0/authorize-derived-keyBackend API endpoint.
If you set
DerivedKeySignature: truewhen making the Backend API request, you can sign the authorize transaction with the derived key right away.
To help you get started with the
authorizeDerivedKeytransaction, we made this node.js code snippet in examples repository that shows this flow.
If everything worked, you should see the derived key listed in the response to the
/api/v0/get-user-derived-keysendpoint with a payload of
PublicKeyBase58Checkset to owner user public key.
While powerful, this model has a limitation.
Namely, it requires the user to have some balance to execute the
This poses a limitation as you won't be able to authorize a derived key for new users who might not have balance in their accounts.
However, in practice, there is no use for derived keys unless the user has some non-zero balance in their account. Otherwise, they wouldn't be able to submit any transactions in the first place.
One possible remedy to this limitation is to send the
authorizeDerivedKeytransaction only when the user wants to perform an action and has sufficient balance, such as giving a like, making a follow, etc.
Another approach is to write a hook that sends the
authorizeDerivedKeytransaction in the background whenever user receives sufficient balance.
This simple background mechanism should mitigate most UX issues.
The private key
derivedSeedHexembedded in the response from Identity's
/derivecan be used to sign transactions on behalf of the
To achieve this, you should construct transactions in the Backend API as if made by the owner’s public key.
You then need to append a field to transaction’s
ExtraData["DerivedPublicKey"]with value set to the derived public key in compressed byte format (33 bytes array) encoded as hex string.
Check out this node.js code snippet in the examples repository for help with compressing the derived public key.
If you have trouble de/serializing transactions to add the
“DerivedPublicKey”to ExtraData, you can use a backend endpoint
/api/v0/append-extra-dataand pass the hex of the transaction and the derived public key like this:
Because of intricacies with transaction fees and ExtraData, you should increase
minFeeRateNanosPerKbto something like
10000when constructing the transaction.
Otherwise, you might get an error while submitting transactions indicating that transaction fee is too low.
Once you have the transaction hex with the derived key in ExtraData, you can sign the transaction with the
derivedSeedHexyou’ve received from identity.
You can also find this example implementation in Go of signing with a derived key corresponding to the admin backend endpoint
Once signed, the transaction can be submitted through the
Note that we didn’t need to communicate with the DeSo Identity at any point in this process.
You can use derived keys to encrypt/decrypt messages on the DeSo blockchain. For more information on our messaging protocol check out the Broken link section.
In order to encrypt/decrypt messages you will need to get shared secrets for each messaging partner of your user.
To get the shared secrets, you can submit requests to the get-shared-secrets endpoint in the window API.
Once you get the shared secrets you can use them to encrypt/decrypt messages.
To help you code this flow, we made a node.js code snippet in the examples repository which displays our messaging protocol.
Identity also offers support for webview, but there are some differences needed in order to fully integrate.
- There is no need to run an iframe context. You will send all messages to one context running in a webview.
- Your webview context will need to have an additional parameter
- Depending on your mobile development framework, you need to make sure messages to and from the webview are being registered appropriately. Currently iOS, Android, and React Native webviews are supported.