Don't encrypt the OTP secret

It doesn't add any security to have this encrypted, but it adds
complexity for podmins, because they need to backup the key.

closes #8014
parent 2d23a260
......@@ -11,7 +11,6 @@ app/assets/images/custom/
# Configuration files
config/diaspora.yml
config/initializers/secret_token.rb
config/initializers/twofa_encryption_key.rb
.bundle
vendor/bundle/
vendor/cache/
......
......@@ -19,11 +19,10 @@ class User < ApplicationRecord
scope :halfyear_actives, ->(time = Time.now) { logged_in_since(time - 6.month) }
scope :active, -> { joins(:person).where(people: {closed_account: false}) }
attribute :otp_secret
attr_encrypted :otp_secret, if: false, prefix: "plain_"
devise :two_factor_authenticatable,
:two_factor_backupable,
otp_secret_encryption_key: AppConfig.twofa_encryption_key,
otp_backup_code_length: 16,
otp_number_of_backup_codes: 10
......
......@@ -2,10 +2,12 @@
class AddDeviseTwoFactorToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :encrypted_otp_secret, :string
add_column :users, :encrypted_otp_secret_iv, :string
add_column :users, :encrypted_otp_secret_salt, :string
add_column :users, :consumed_timestep, :integer
add_column :users, :otp_required_for_login, :boolean
change_table :users, bulk: true do |t|
t.string :encrypted_otp_secret
t.string :encrypted_otp_secret_iv
t.string :encrypted_otp_secret_salt
t.integer :consumed_timestep
t.boolean :otp_required_for_login
end
end
end
# frozen_string_literal: true
class DecryptTwoFactorSecret < ActiveRecord::Migration[5.1]
class User < ApplicationRecord
end
def up
add_column :users, :plain_otp_secret, :string
key = twofa_encryption_key
decrypt_existing_secrets(key) if key
change_table :users, bulk: true do |t|
t.remove :encrypted_otp_secret
t.remove :encrypted_otp_secret_iv
t.remove :encrypted_otp_secret_salt
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
private
def twofa_encryption_key
if AppConfig.heroku?
ENV["TWOFA_ENCRYPTION_KEY"]
else
key_file = File.expand_path("../../config/initializers/twofa_encryption_key.rb", File.dirname(__FILE__))
if File.exist? key_file
require key_file
File.delete(key_file)
return Diaspora::Application.config.twofa_encryption_key
end
end
end
def decrypt_existing_secrets(key)
User.where.not(encrypted_otp_secret: nil).each do |user|
user.plain_otp_secret = Encryptor.decrypt(
value: user.encrypted_otp_secret.unpack("m").first,
key: key,
iv: user.encrypted_otp_secret_iv.unpack("m").first,
salt: user.encrypted_otp_secret_salt.slice(1..-1).unpack("m").first
)
user.save!
end
end
end
......@@ -68,24 +68,6 @@ module Configuration
end
end
def twofa_encryption_key
if heroku?
return ENV["TWOFA_ENCRYPTION_KEY"] if ENV["TWOFA_ENCRYPTION_KEY"]
warn "FATAL: Running on Heroku with TWOFA_ENCRYPTION_KEY unset"
warn " Run heroku config:add TWOFA_ENCRYPTION_KEY=#{SecureRandom.hex(32)}"
abort
else
key_file = File.expand_path(
"../config/initializers/twofa_encryption_key.rb",
File.dirname(__FILE__)
)
system "DISABLE_SPRING=1 bin/rake generate:twofa_key" unless File.exist? key_file
require key_file
Diaspora::Application.config.twofa_encryption_key
end
end
def version_string
return @version_string unless @version_string.nil?
......
# frozen_string_literal: true
namespace :generate do
desc "Generates a key for encrypting 2fa tokens"
task :twofa_key do
path = Rails.root.join("config", "initializers", "twofa_encryption_key.rb")
key = SecureRandom.hex(32)
File.open(path, "w") do |f|
f.write <<~CONF
# frozen_string_literal: true
# The 2fa encryption key is used to encrypt users' OTP tokens in the database.
# You can regenerate this key by running `rake generate:twofa_key`
# If you change this key after a user has set up 2fa
# the users' tokens cannot be recovered
# and they will not be able to log in again!
Diaspora::Application.config.twofa_encryption_key = "#{key}"
CONF
end
end
end
......@@ -984,9 +984,7 @@ describe User, :type => :model do
exported_at
exported_photos_at
consumed_timestep
encrypted_otp_secret
encrypted_otp_secret_iv
encrypted_otp_secret_salt
plain_otp_secret
otp_backup_codes
otp_required_for_login
otp_secret
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment