Encryption in FIO Request and FIO Data

Overview

Certain sensitive data in /new_funds_request and /record_obt_data is encrypted using the Diffie-Hellman key exchange scheme. In a nutshell, to encrypt the data, the sender uses its private key and the public key of the receiver. To decrypt the data, the receiver uses its private key and the public key of the sender. This ensures that only the sender and receiver of the data can decrypt it.

The data is further serialized to reduce size. Currently there is no abi for that data, but you can find the relevant data elements inside /new_funds_request and /record_obt_data action spec.

For those unfamiliar with Diffie-Hellman encryption, methods in fiojs SDK make this easy.

Integration Considerations

Encryption/decryption inside the wallet

Because the encryption/decryption requires a private key of sender or receiver, it can only be done inside the wallet hosting the required private key.

Setting different encrypt key

By default, the FIO Private Key which secures the account is the same key used for encryption/decryption. However, a different key can be set using updcryptkey action. This is useful, if the FIO Handle owner wants to change the FIO Public Key which is mapped to FIO Handle.

🚧

Update Encrypt Key

If your application lets the user update a FIO Public Key which is mapped to their FIO Handle using addaddress action, it is recommended that you update the encrypt key to the public key which corresponds to the private key which secures the account. If you fail to properly set the encrypt key, your application may not be able to properly encrypt/decrypt FIO Request and FIO Data.

Example:

  • User's default private key is SK1 which maps to PK1
  • User registers FIO Handle FH1
  • PK1 is automatically mapped to FH1 for FIO Tokens
  • Since encrypt key is not set by default the /get_encrypt_key will return PK1 and it will be used for encryption
  • User now maps PK2 to FH1 for FIO Tokens
  • Since encrypt key is still not set the /get_encrypt_key will now return PK2 and it will be used for encryption. If your application has access to corresponding SK2, that is fine. However, if you do not and you would like to continue to use SK1 for encryption/decryption, you must update the encrypt key to PK1 using updcryptkey action. /get_encrypt_key will now return PK1, while /get_pub_address for FIO Tokens will return PK2.

Using correct Public Key when encrypting data

When encrypting data your application needs to have access to your user's private key and the other user's public key. Historically, that public key was fetched using /get_pub_address getter for FIO-FIO. However, since release 1.9/3.5/2.9 it should be fetched using /get_encrypt_key. If you are using SDK 1.9 or later, this will be handled for you.

❗️

If not using SDK 1.9 or later

If you have implemented your own encryption or are using legacy SDKs, update it to fetch other party's FIO Public Key using /get_encrypt_key getter instead of /get_pub_address.

Using correct Private Public Keys when decrypting data

It's important that the correct private/public keys are used to decrypt an existing FIO Data or FIO Request record, especially since those keys can change over time. For that purpose, the getters which return the encrypted blob (/get_pending_fio_requests, /get_sent_fio_requests, /get_received_fio_requests, /get_cancelled_fio_requests, /get_obt_data) also return payer_fio_public_key, payee_fio_public_key, which were used during the initial encryption.

When decrypting the content match the keys as follows:

GetterDescriptionPrivate KeyPublic Key
/get_pending_fio_requests
/get_received_fio_requests
Typically used by the receiver of the FIO RequestPrivate key which hashes to payer_fio_public_key returnedpayee_fio_public_key
/get_sent_fio_requests
/get_cancelled_fio_requests
Typically used by the sender of the FIO RequestPrivate key which hashes to payee_fio_public_key returnedpayer_fio_public_key
/get_obt_dataTypically used by the receiver of the FIO DataPrivate key which hashes to payee_fio_public_key returnedpayer_fio_public_key

Validation

🚧

Data validation

The FIO Chain is not able to access the unencrypted data, so no validation is performed on the data in the content field. It is up to the wallet to ensure the data received is properly formatted and handle any exceptions.

As an example, it is recommended chain_code and token_code be converted to upper case to mitigate the risk that the sending entity used lower case.

Size limitations on encrypted data

Since the FIO Chain is not able to access the unencrypted content, it cannot enforce size limitations on the individual fields. Size limitation is therefore enforced on the content field containing the encrypted string.

MethodMinimum charactersMaximum characters
/new_funds_request64296
/record_obt_data64432

Once you factor encryption overhead the available characters for all parameters are:

MethodMaximum characters
/new_funds_request145
/record_obt_data260

Memo field size in FIO Request

Assuming typical FIO Request contains the following required parameters:

ParameterTypical size
payee_public_address50
amount8
chain_code3
token_code3

This would allow for a memo field to be as long as 81 characters. However, some blockchains can have public addresses of over 100 characters, which can severely limit the characters available for memo.

It is recommended that the memo restrictions are computed dynamically based on public address and amount entered.