Every LockerX user has available a Stellar wallet they can use to create smart contracts.
To access your wallet (identified by its public key), you need to use the corresponding secret key that is known only to you. Usually, the secret key is safely stored by the wallet software you use. Knowing an account’s secret key gives complete control over it, it is then clear that the secret key should never be shared with anyone and should be kept as safe as possible.
Every time you create a smart contract using LockerX, we will create a new Stellar account on the network for the smart contract. This means that we have to manage hundreds or thousands of secret keys, and make sure they are safe!
The basics of keeping keys secure are:
When we started this project, we decided to use Google Cloud because of its security-focused features and the simplicity of the platform.
The Stellar secret keys are encrypted using envelope encryption (described in the next section), using keys managed by Google Cloud KMS and stored in Google Cloud SQL, which is encrypted at rest by default.
Knowing how keys are used is an important component of secret key management, Google Cloud provides audit logs that can be used to understand which services have been using KMS keys for encryption and decryption. This feature allows us to monitor the infrastructure to detect unauthorized access to the secret keys.
Envelope encryption is a technique where one key is encrypted using another key. One key, the Data Encryption Key (DEK), is used to encrypt the data itself. The DEK is then encrypted using a Key Encryption Key (KEK).
The DEK is generated locally and is stored (encrypted) together with the Stellar key it encrypts. DEKs are used to encrypt only one Stellar key and never reused, for this reason, they don’t need to be rotated.
We use Cloud KMS to centrally manage and store KEKs. KEKs are regularly rotated. KEKs are never transmitted over the network to our application, instead, we use the Cloud KMS API to encrypt and decrypt the DEKs.
The process to create and encrypt a Stellar key is:
When we need to retrieve the Stellar key:
The image below shows how the DEK is used to encrypt the Stellar key and is then encrypted using the KEK managed by the KMS. The encrypted Stellar key and DEK are then saved to Cloud SQL.
Secret keys should never be transmitted over the network, this means that transactions can’t be signed by individual services and instead have to be signed by a centralized service. This is the job of the signing service.
The signing service is responsible for:
All other services that need to sign data to submit a transaction to the network will need to make an API call to the signing service.
As an example, the service responsible for creating smart contracts requests the signing service to generate a new account id and then store the account id together with the smart contract.
When it’s time to sign and submit the transaction, the smart contract service requests the signing service to sign the transaction using the contract key, and then sends the signed transaction to the network.
In this post, we discussed how we store Stellar secret keys at LockerX. The intent of this post is to be a starting point for developers looking to store users' secret keys securely. Storing secret keys should be done only when strictly necessary since it makes your application a much nicer target for attackers (it’s the ultimate bug bounty program). When possible, projects should delegate transaction signing to the user wallet.