Loading README.md +6 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 ------------------------------------- Loading Loading @@ -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 \ Loading @@ -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 \ Loading bin/trees-create +31 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ 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" Loading @@ -37,6 +38,9 @@ def usage 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 Loading @@ -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 Loading @@ -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 if old_password.nil? st.generate_new_keypair(password) else st.change_password(old_password, password) end puts st.to_s end Loading Loading @@ -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] Loading src/trees-plugin.h +2 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading
README.md +6 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 ------------------------------------- Loading Loading @@ -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 \ Loading @@ -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 \ Loading
bin/trees-create +31 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ 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" Loading @@ -37,6 +38,9 @@ def usage 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 Loading @@ -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 Loading @@ -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 if old_password.nil? st.generate_new_keypair(password) else st.change_password(old_password, password) end puts st.to_s end Loading Loading @@ -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] Loading
src/trees-plugin.h +2 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading