docs: public EncryptionKey generateAndSaveKeyProtectedByPassword(String password) {
          EncryptionKey dpk = null;
          if (password == null || password.equals("")) {
              throw new IllegalArgumentException("password is required to be a non-null/non-empty " +
                      "string");
          }
          try {
              if (!keyExists()) {
                  byte[] dpkBytes = generateSecureRandomBytesWithLength
                          (ENCRYPTION_KEYCHAIN_ENCRYPTIONKEY_SIZE);
                  byte[] salt = generateSecureRandomBytesWithLength
                          (ENCRYPTION_KEYCHAIN_PBKDF2_SALT_SIZE);
                  byte[] iv = generateSecureRandomBytesWithLength
                          (ENCRYPTIONKEYCHAINMANAGER_AES_IV_SIZE);
                  SecretKey aesKey = pbkdf2DerivedKeyForPassword(password, salt,
                          ENCRYPTION_KEYCHAIN_PBKDF2_ITERATIONS,
                          ENCRYPTION_KEYCHAIN_AES_KEY_SIZE);
  
                  byte[] encryptedDpkBytes = DPKEncryptionUtil.encryptAES(aesKey, iv, dpkBytes);
  
                  KeyData keyData = new KeyData(encryptedDpkBytes, salt, iv,
                          ENCRYPTION_KEYCHAIN_PBKDF2_ITERATIONS, ENCRYPTION_KEYCHAIN_VERSION);
  
                  if (this.storage.saveEncryptionKeyData(keyData)) {
                      dpk = new EncryptionKey(dpkBytes);
                  }
              }
          } catch (InvalidKeyException e) {
              throw new DPKException("Failed to encrypt DPK.  Cause: " + e.getLocalizedMessage(), e);
          } catch (NoSuchPaddingException e) {
              throw new DPKException("Failed to encrypt DPK.  Cause: " + e.getLocalizedMessage(), e);
          } catch (NoSuchAlgorithmException e) {
              throw new DPKException("Failed to encrypt DPK.  Cause: " + e.getLocalizedMessage(), e);
          } catch (IllegalBlockSizeException e) {
              throw new DPKException("Failed to encrypt DPK.  Cause: " + e.getLocalizedMessage(), e);
          } catch (BadPaddingException e) {
              throw new DPKException("Failed to encrypt DPK.  Cause: " + e.getLocalizedMessage(), e);
          } catch (InvalidAlgorithmParameterException e) {
              throw new DPKException("Failed to encrypt DPK.  Cause: " + e.getLocalizedMessage(), e);
          } catch (InvalidKeySpecException e) {
              throw new DPKException("Failed to encrypt DPK.  Cause: " + e.getLocalizedMessage(), e);
          }
          return dpk;
      }