To give your users access to their encrypted data from more than one device, you need to back up their private key using E3Kit. The E3Kit eThree.backupPrivateKey() method requires setting up a password to verify that it's actually the correct user attempting to access their encrypted data. It's highly encouraged that developers require this password to be strong, generated and managed by the user, and distinct from the password a user uses to log in to the application. 

But maybe you have a passwordless application or there's some other reason that your app flow requires you to store these private key backup passwords in your database. If that's the case, protecting these passwords is very important, because if someone accesses these passwords, they can access your users' private keys and therefore their encrypted data. 

Please follow these steps to protect the backup passwords using a master keypair:

virgil keygen -o <private_key_file_name>  -p <password>
  • Store the key's file somewhere secure on the application server. 

The key's file should be stored as far away as possible from the database with passwords. Also, it's highly recommend to protect the key's file using an ACL.

Loading the Master KeyPair

const fs = require('fs');
const { VirgilCrypto } = require('virgil-crypto');

const virgilCrypto = new VirgilCrypto();

// Note that the master private key in this example is loaded from the file system, which means
// that this will only work if your server is running on a single physical machine (or VM).
// If you app can have multiple server instances running on different physical machines (or VMs)
// you'll need to store and load the master private key from some shared location, for example,
// from a dedicated server that is only available from internal network

function loadMasterKeyPair() {
  // Assuming environment variables MASTER_PRIVATE_KEY_PATH and MASTER_PRIVATE_KEY_PASSWORD
  // are populated with the location of the <private_key_file_name> in the file system and
  // the <password> used with virgil keygen command
  const masterPrivateKeyData = fs.readFileSync(process.env.MASTER_PRIVATE_KEY_PATH);

  const masterPrivateKey = virgilCrypto.importPrivateKey(masterPrivateKeyData, process.env.MASTER_PRIVATE_KEY_PASSWORD);

  const masterPublicKey = virgilCrypto.extractPublicKey(masterPrivateKey);

  return {
    privateKey: masterPrivateKey,
    publicKey: masterPublicKey
  };

}

Using the Master Keypair

const masterKeyPair = loadMasterKeyPair();

function saveUserBackupPassword(userId, backupPassword) {
  const encryptedBackupPassword = virgilCrypto.encrypt(backupPassword, masterKeyPair.publicKey);

  // this is completely made up. this will be different in different applications
  return db.BackupPasswords.save({ userId: userId, encryptedBackupPassword: encryptedBackupPassword.toString('base64') });

}

function loadUserBackupPassword(userId) {
  return db.BackupPasswords.loadByUserId(userId)
    .then(encryptedBackupPassword => {
      return virgilCrypto.decrypt(encryptedBackupPassword, masterKeyPair.privateKey).toString('utf8');
    });
}


Please contact us with any questions or to confirm your implementation is correct.

Did this answer your question?