Skip to content

Encrypt passwords with PBKDF2 with SHA512

Drew Blessing requested to merge dblessing_devise_encryptable into master

Related to #360658 (closed)

Encrypt all new passwords with PBKDF2 with SHA512 and migrate from BCrypt to PBKDF2 with SHA512 each time the user's password is compared.

Risks

  • If something goes wrong users may lose access to their accounts. If we have to disable the feature flag, any user who had their password migrated will be unable to sign in without resetting their password.
  • The volume of database writes from people signing in could be an issue for a period of time.
    • Should we implement a feature flag on the migration portion that allows us to roll out slowly? We leave the new authentication and fall-through in place so people can sign in regardless of whether they have BCrypt or PBKDF2 with SHA512 passwords. But we only migrate a % at a time.

Database

We have to add this to the users table, despite it being an already very wide table, because it's expected for Devise to work properly.

Migrate

$ migrate
== 20220518155119 AddPasswordSaltToUsers: migrating ===========================
-- transaction_open?()
   -> 0.0000s
-- column_exists?(:users, :password_salt)
   -> 0.0042s
-- add_column(:users, :password_salt, :text)
   -> 0.0008s
-- transaction_open?()
   -> 0.0000s
-- current_schema()
   -> 0.0001s
-- transaction_open?()
   -> 0.0000s
-- execute("ALTER TABLE users\nADD CONSTRAINT check_fe3ed6db15\nCHECK ( char_length(password_salt) <= 20 )\nNOT VALID;\n")
   -> 0.0006s
-- current_schema()
   -> 0.0001s
-- execute("SET statement_timeout TO 0")
   -> 0.0002s
-- execute("ALTER TABLE users VALIDATE CONSTRAINT check_fe3ed6db15;")
   -> 0.0005s
-- execute("RESET statement_timeout")
   -> 0.0003s
== 20220518155119 AddPasswordSaltToUsers: migrated (0.0151s) ==================

Rollback

$ bundle exec rails db:rollback:main
== 20220518155119 AddPasswordSaltToUsers: reverting ===========================
-- transaction_open?()
   -> 0.0000s
-- column_exists?(:users, :password_salt)
   -> 0.0045s
-- remove_column(:users, :password_salt)
   -> 0.0008s
-- transaction_open?()
   -> 0.0000s
-- transaction_open?()
   -> 0.0000s
-- execute("ALTER TABLE users\nDROP CONSTRAINT IF EXISTS check_fe3ed6db15\n")
   -> 0.0003s
== 20220518155119 AddPasswordSaltToUsers: reverted (0.0122s) ==================
Edited by Drew Blessing

Merge request reports