diff --git a/README.md b/README.md
index 50c424cbd9fd41615f2744437614779c70e2d5b7..6e6f467c37bc42f3f18dc02929695438215b28b2 100644
--- a/README.md
+++ b/README.md
@@ -84,7 +84,9 @@ An example database scheme for this might be:
     CREATE TABLE `storage_keys` (
       `id` int(11) NOT NULL AUTO_INCREMENT,
       `enabled` tinyint(4) DEFAULT '1',
+      `version` tinyint(4) DEFAULT '1',
       `public_key` text,
+      `pwhash_algo` tinyint(4) DEFAULT '1',
       `pwhash_opslimit` int(11) DEFAULT NULL,
       `pwhash_memlimit` int(11) DEFAULT NULL,
       `pwhash_salt` varchar(255) DEFAULT NULL,
@@ -98,6 +100,7 @@ NOTE: the database MUST NOT store the argon2 digest, since this value is the
 secret key that unlocks `locked_secretbox`. This is very different than how
 password hashing for authentication works, where the digest and parameters are
 stored.
+pwhash_algo is 0 for libsodium <= 1.0.14 and 1 for libsodium >= 1.0.15
 
 Dovecot Configuration
 -------------------------------------
@@ -157,9 +160,11 @@ Here is a dovecot SQL query configuration that will work with the sample
       CONCAT('/maildir/', mailboxes.maildir)    AS userdb_home, \
       REPLACE('%w', '%%', '%%%%')               AS userdb_trees_password, \
       storage_keys.enabled                      AS userdb_trees_enabled, \
+      storage_keys.version                      AS userdb_trees_version, \
       storage_keys.public_key                   AS userdb_trees_public_key, \
       storage_keys.locked_secretbox             AS userdb_trees_locked_secretbox, \
       storage_keys.sk_nonce                     AS userdb_trees_sk_nonce, \
+      storage_keys.pwhash_algo                  AS userdb_trees_pwhash_algo, \
       storage_keys.pwhash_opslimit              AS userdb_trees_pwhash_opslimit, \
       storage_keys.pwhash_memlimit              AS userdb_trees_pwhash_memlimit, \
       storage_keys.pwhash_salt                  AS userdb_trees_pwhash_salt \
@@ -180,6 +185,7 @@ Here is a dovecot SQL query configuration that will work with the sample
       8                                         AS gid, \
       CONCAT('/maildir/', mailboxes.maildir)    AS home, \
       storage_keys.enabled                      AS trees_enabled, \
+      storage_keys.version                      AS userdb_trees_version, \
       storage_keys.public_key                   AS trees_public_key, \
       CONCAT('*:bytes=', mailboxes.quota)       AS quota_rule \
       FROM mailboxes \
diff --git a/bin/trees-create b/bin/trees-create
index 8c4f8856d0af9c17c882ec5c177f2a183d91a52e..2bb1eee90ebc1c80df0e8f5c1a03fdfe4908105f 100755
--- a/bin/trees-create
+++ b/bin/trees-create
@@ -27,16 +27,20 @@ end
 def usage
   puts "USAGE:"
   puts "   trees-create --password PASSWORD [OPTIONS]"
+  puts "   trees-create --password PASSWORD --old-password PASSWORD OPTIONS"
   puts
   puts "OPTIONS may include:"
-  puts "   --opslimit OPSLIMIT -- argon2 ops limit, integer in 3..10, or one of"
-  puts "                          'interactive', 'moderate', 'sensitive'"
-  puts "   --memlimit MEMLIMIT -- argon2 memory limit, in bytes, or one of"
-  puts "                          'interactive', 'moderate', 'sensitive'"
-  puts "   --salt SALT         -- hex encoded salt for password digest,"
-  puts "                          #{StorageKey::SALT_BYTES} bytes in length"
-  puts "   --nonce NONCE       -- hex encoded nonce for secretbox encryption of"
-  puts "                          private key, #{StorageKey::NONCE_BYTES} bytes in length"
+  puts "   --opslimit OPSLIMIT     -- argon2 ops limit, integer in 3..10, or one of"
+  puts "                              'interactive', 'moderate', 'sensitive'"
+  puts "   --memlimit MEMLIMIT     -- argon2 memory limit, in bytes, or one of"
+  puts "                              'interactive', 'moderate', 'sensitive'"
+  puts "   --salt SALT             -- hex encoded salt for password digest,"
+  puts "                              #{StorageKey::SALT_BYTES} bytes in length"
+  puts "   --nonce NONCE           -- hex encoded nonce for secretbox encryption of"
+  puts "                              private key, #{StorageKey::NONCE_BYTES} bytes in length"
+  puts "   --secretbox SECRETBOX   -- hex encoded secretbox"
+  puts
+  puts "for password change all options are required"
   exit 1
 end
 
@@ -46,6 +50,9 @@ def main
 
   while ARGV.any?
     case ARGV.first
+    when "--old-password"
+      ARGV.shift
+      old_password = ARGV.shift
     when "--password"
       ARGV.shift
       password = ARGV.shift
@@ -61,12 +68,19 @@ def main
     when "--nonce"
       ARGV.shift
       st.sk_nonce = ARGV.shift
+    when "--secretbox"
+      ARGV.shift
+      st.locked_secretbox = ARGV.shift
     else
       usage
     end
   end
   usage unless password
-  st.generate_new_keypair(password)
+  if old_password.nil?
+    st.generate_new_keypair(password)
+  else
+    st.change_password(old_password, password)
+  end
   puts st.to_s
 end
 
@@ -121,6 +135,14 @@ class StorageKey
     )
   end
 
+  def change_password(old_password, password)
+    key = self.decrypt_key(old_password)
+    self.encrypt_key(
+      key: key,
+      password: password
+    )
+  end
+
   def to_s
     attrs = [:public_key, :locked_secretbox, :sk_nonce, :pwhash_opslimit,
              :pwhash_memlimit, :pwhash_salt]
diff --git a/src/trees-plugin.h b/src/trees-plugin.h
index c6fd36e26191d3d4045510b767b5febdf5279433..d3da04f14f84f5e13fca269392fa5498b139504c 100644
--- a/src/trees-plugin.h
+++ b/src/trees-plugin.h
@@ -33,9 +33,11 @@ trees_pluging_pwhash_map(int value)
 	case 0:
 		/* argon2i, libsodium <= 1.0.14. */
 		return crypto_pwhash_ALG_ARGON2I13;
+#ifdef crypto_pwhash_ALG_ARGON2IDI3
 	case 1:
 		/* argon2id, libsodium >= 1.0.15 */
 		return crypto_pwhash_ALG_ARGON2ID13;
+#endif
 	default:
 		return -1;
 	}