An unofficial, mostly Bitwarden-compatible API server written in Ruby (Sinatra and ActiveRecord)

tools/change_master_password: support changing KDF iterations

closes #90

+25 -4
+5 -3
lib/user.rb
··· 71 71 self.totp_secret.present? 72 72 end 73 73 74 - def update_master_password(old_pwd, new_pwd) 74 + def update_master_password(old_pwd, new_pwd, 75 + new_kdf_iterations = self.kdf_iterations) 75 76 # original random encryption key must be preserved, just re-encrypted with 76 77 # a new key derived from the new password 77 78 ··· 81 82 82 83 self.key = Bitwarden.encrypt(orig_key, 83 84 Bitwarden.makeKey(new_pwd, self.email, 84 - Bitwarden::KDF::TYPES[self.kdf_type], self.kdf_iterations)).to_s 85 + Bitwarden::KDF::TYPES[self.kdf_type], new_kdf_iterations)).to_s 85 86 86 87 self.password_hash = Bitwarden.hashPassword(new_pwd, self.email, 87 - self.kdf_type, self.kdf_iterations) 88 + self.kdf_type, new_kdf_iterations) 89 + self.kdf_iterations = new_kdf_iterations 88 90 self.security_stamp = SecureRandom.uuid 89 91 end 90 92
+20 -1
tools/change_master_password.rb
··· 87 87 end 88 88 end 89 89 90 - @u.update_master_password(password, new_master) 90 + new_kdf_iterations = nil 91 + while new_kdf_iterations.to_s == "" 92 + print "kdf iterations (currently #{@u.kdf_iterations}, default " << 93 + "#{Bitwarden::KDF::DEFAULT_ITERATIONS[@u.kdf_type]}): " 94 + new_kdf_iterations = STDIN.gets.chomp 95 + 96 + if new_kdf_iterations.to_s == "" 97 + new_kdf_iterations = Bitwarden::KDF::DEFAULT_ITERATIONS[@u.kdf_type] 98 + break 99 + elsif !(r = Bitwarden::KDF::ITERATION_RANGES[@u.kdf_type]). 100 + include?(new_kdf_iterations.to_i) 101 + puts "iterations must be between #{r}" 102 + new_kdf_iterations = nil 103 + else 104 + new_kdf_iterations = new_kdf_iterations.to_i 105 + break 106 + end 107 + end 108 + 109 + @u.update_master_password(password, new_master, new_kdf_iterations) 91 110 @u.password_hint = new_master_hint 92 111 if !@u.save 93 112 puts "error saving new password"