diff --git a/VERSION b/VERSION
index a75b92f1e..ef425ca98 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-5.1
+5.2
diff --git a/app/controllers/api/teams_controller.rb b/app/controllers/api/teams_controller.rb
index 8a5a6abe8..ad3ab9d6a 100644
--- a/app/controllers/api/teams_controller.rb
+++ b/app/controllers/api/teams_controller.rb
@@ -17,7 +17,7 @@ class Api::TeamsController < ApiController
# GET /api/teams
def index
if team_id.present?
- authorize Team.find(team_id), :team_member?
+ fetch_team
elsif params['only_teammember_user_id'].present?
authorize ::Team, :only_teammember?
else
@@ -28,6 +28,32 @@ def index
private
+ def fetch_team
+ @team = Team.find(team_id)
+ authorize @team, :team_member?
+
+ unless already_recrypted?(@team)
+ receive_transferred_encryptables(@team) if team.personal_team?
+ recrypt(@team)
+ end
+ end
+
+ def receive_transferred_encryptables(team)
+ team.encryptables.select(&:transferred?).each do |encryptable|
+ team_password = decrypted_team_password(team)
+ EncryptableTransfer.new.receive(encryptable, session[:private_key], team_password)
+ end
+ end
+
+ def already_recrypted?(team)
+ Crypto::Symmetric.latest_algorithm?(team)
+ end
+
+ def recrypt(team)
+ private_key = session[:private_key]
+ Crypto::Symmetric::Recrypt.new(current_user, team, private_key).perform
+ end
+
def build_entry
instance_variable_set(:"@#{ivar_name}",
Team::Shared.create(current_user, model_params))
diff --git a/app/models/encryptable.rb b/app/models/encryptable.rb
index 13a07ff89..c7cfc8f39 100644
--- a/app/models/encryptable.rb
+++ b/app/models/encryptable.rb
@@ -17,6 +17,8 @@
class Encryptable < ApplicationRecord
serialize :encrypted_data, ::EncryptedData
+ class_attribute :used_encrypted_attrs
+
attr_readonly :type
validates :type, presence: true
@@ -26,12 +28,25 @@ class Encryptable < ApplicationRecord
validates :name, presence: true
validates :description, length: { maximum: 4000 }
- def encrypt(_team_password)
- raise 'implement in subclass'
+ def encrypt(team_password, encryption_algorithm = nil)
+ used_encrypted_attrs.each do |a|
+ encrypt_attr(a, team_password, encryption_algorithm)
+ end
end
- def decrypt(_team_password)
- raise 'implement in subclass'
+ def decrypt(team_password)
+ encrypted_attrs = encrypted_data.used_attributes
+ encrypted_attrs.each do |a|
+ decrypt_attr(a, team_password)
+ end
+ end
+
+ def recrypt(team_password, new_team_password, new_encryption_class)
+ decrypt(team_password)
+
+ @new_encryption_class = new_encryption_class
+ encrypt(new_team_password)
+ save!
end
def self.policy_class
@@ -75,30 +90,27 @@ def used_encrypted_data_attrs
private
- def encrypt_attr(attr, team_password)
+ def encrypt_attr(attr, team_password, encryption_algorithm = nil)
cleartext_value = send(:"cleartext_#{attr}")
- encrypted_value = if cleartext_value.presence
- Crypto::Symmetric::Aes256.encrypt(cleartext_value, team_password)
- end
+ encrypted_value =
+ encrypt_with_encryption_class(cleartext_value, team_password, encryption_algorithm)
return if transferred? && encrypted_value.blank?
- build_encrypted_data(attr, encrypted_value)
- end
-
- def build_encrypted_data(attr, encrypted_value)
attr_label = cleartext_custom_attr_label if attr == :custom_attr
- encrypted_data.[]=(
- attr, **{ label: attr_label, data: encrypted_value, iv: nil }
- )
+ encrypted_data.[]=(attr, **{
+ label: attr_label,
+ data: encrypted_value[:data],
+ iv: encrypted_value[:iv]
+ })
end
def decrypt_attr(attr, team_password)
- encrypted_value = encrypted_data[attr].try(:[], :data)
+ encrypted_value = encrypted_value_hash(attr)
- cleartext_value = if encrypted_value
- Crypto::Symmetric::Aes256.decrypt(encrypted_value, team_password)
+ cleartext_value = if encrypted_value[:data].present?
+ encryption_class.decrypt(encrypted_value, team_password)
end
if attr == :custom_attr
@@ -108,6 +120,27 @@ def decrypt_attr(attr, team_password)
instance_variable_set("@cleartext_#{attr}", cleartext_value)
end
+ def encrypted_value_hash(attr)
+ data_attr = encrypted_data[attr]
+
+ data = data_attr.try(:[], :data)
+ iv = data_attr.try(:[], :iv)
+ { data: data, iv: iv }
+ end
+
+ def encrypt_with_encryption_class(cleartext_value, team_password, encryption_algorithm)
+ if cleartext_value.presence
+ @new_encryption_class = encryption_algorithm unless encryption_algorithm.nil?
+ encryption_class.encrypt(cleartext_value, team_password)
+ else
+ { data: nil, iv: nil }
+ end
+ end
+
+ def encryption_class
+ @new_encryption_class || team.encryption_class
+ end
+
def assert_human_receiver?
unless User.find(receiver_id).is_a?(User::Human)
errors.add(:receiver_id, 'Must be a human user')
diff --git a/app/models/encryptable/credentials.rb b/app/models/encryptable/credentials.rb
index 75ca54e2a..584eb9cba 100644
--- a/app/models/encryptable/credentials.rb
+++ b/app/models/encryptable/credentials.rb
@@ -4,6 +4,8 @@ class Encryptable::Credentials < Encryptable
attr_accessor :cleartext_password, :cleartext_username, :cleartext_token, :cleartext_pin,
:cleartext_email, :cleartext_custom_attr_label, :cleartext_custom_attr
+ self.used_encrypted_attrs = [:username, :password, :token, :pin, :email, :custom_attr].freeze
+
has_many :encryptable_files,
class_name: 'Encryptable::File',
foreign_key: :credential_id,
@@ -12,23 +14,4 @@ class Encryptable::Credentials < Encryptable
validates :name, length: { maximum: 70 }
validates :name, uniqueness: { scope: :folder }
validates :folder_id, presence: true
-
- def decrypt(team_password)
- decrypt_attr(:username, team_password)
- decrypt_attr(:password, team_password)
- decrypt_attr(:token, team_password)
- decrypt_attr(:pin, team_password)
- decrypt_attr(:email, team_password)
- decrypt_attr(:custom_attr, team_password)
- end
-
- def encrypt(team_password)
- encrypt_attr(:username, team_password)
- encrypt_attr(:password, team_password)
- encrypt_attr(:token, team_password)
- encrypt_attr(:pin, team_password)
- encrypt_attr(:email, team_password)
- encrypt_attr(:custom_attr, team_password)
- end
-
end
diff --git a/app/models/encryptable/file.rb b/app/models/encryptable/file.rb
index ba5e5eebb..c8724b944 100644
--- a/app/models/encryptable/file.rb
+++ b/app/models/encryptable/file.rb
@@ -3,6 +3,8 @@
class Encryptable::File < Encryptable
attr_accessor :cleartext_file
+ self.used_encrypted_attrs = [:file].freeze
+
belongs_to :encryptable_credential,
class_name: 'Encryptable::Credentials',
foreign_key: :credential_id
@@ -11,16 +13,6 @@ class Encryptable::File < Encryptable
validate :file_size, on: [:create, :update]
- def decrypt(team_password)
- decrypt_attr(:file, team_password)
- end
-
- def encrypt(team_password)
- return if cleartext_file.empty?
-
- encrypt_attr(:file, team_password)
- end
-
def team
folder&.team || encryptable_credential.folder.team
end
diff --git a/app/models/encrypted_data.rb b/app/models/encrypted_data.rb
index ce4e64fe2..d2e056f70 100644
--- a/app/models/encrypted_data.rb
+++ b/app/models/encrypted_data.rb
@@ -21,15 +21,19 @@ def []=(key, data:, iv:, label: nil)
end
def to_json(*_args)
- @data.reject { |_, value| value[:data].blank? }.to_json
+ present_data.to_json
end
def used_attributes
- @data.keys.map(&:to_s)
+ present_data.keys
end
private
+ def present_data
+ @data.reject { |_, value| value[:data].blank? }
+ end
+
def data_hash(iv, data, label = nil)
hash = { iv: iv, data: data }
hash[:label] = label if label
diff --git a/app/models/team.rb b/app/models/team.rb
index 2e8a961fe..bf25c0ea7 100644
--- a/app/models/team.rb
+++ b/app/models/team.rb
@@ -23,6 +23,16 @@ class Team < ApplicationRecord
validates :name, presence: true
validates :name, length: { maximum: 40 }
validates :description, length: { maximum: 300 }
+ validates :encryption_algorithm,
+ inclusion: { in: ::Crypto::Symmetric::ALGORITHMS.keys }, allow_nil: false
+
+ after_initialize :set_encryption_algorithm, if: :new_record?
+
+ enum recrypt_state: {
+ failed: 0,
+ done: 1,
+ in_progress: 2
+ }, _prefix: :recrypt
def label
name
@@ -41,8 +51,8 @@ def teammember(user_id)
end
def decrypt_team_password(user, plaintext_private_key)
- crypted_team_password = teammember(user.id).password
- Crypto::Rsa.decrypt(crypted_team_password, plaintext_private_key)
+ encrypted_team_password = teammember(user.id).encrypted_team_password
+ Crypto::Rsa.decrypt(encrypted_team_password, plaintext_private_key)
end
def personal_team?
@@ -60,10 +70,31 @@ def self.policy_class
TeamPolicy
end
+ def encryption_class
+ Crypto::Symmetric::ALGORITHMS[encryption_algorithm]
+ end
+
+ def password_bitsize
+ encryption_class.password_bitsize
+ end
+
+ def new_team_password
+ encryption_class.random_key
+ end
+
+ def encryptables
+ encryptable_ids = Encryptable.joins(folder: :team).where('teams.id': id).pluck(:id)
+ Encryptable.where(id: encryptable_ids).or(Encryptable.where(credential_id: encryptable_ids))
+ end
+
private
def create_teammember(user, plaintext_team_password)
encrypted_team_password = Crypto::Rsa.encrypt(plaintext_team_password, user.public_key)
- teammembers.create!(password: encrypted_team_password, user: user)
+ teammembers.create!(encrypted_team_password: encrypted_team_password, user: user)
+ end
+
+ def set_encryption_algorithm
+ self.encryption_algorithm = Crypto::Symmetric::LATEST_ALGORITHM
end
end
diff --git a/app/models/team/personal.rb b/app/models/team/personal.rb
index cae7dadf4..e59911c08 100644
--- a/app/models/team/personal.rb
+++ b/app/models/team/personal.rb
@@ -21,7 +21,7 @@ def create(owner)
team = super(name: 'personal-team', personal_owner: owner, private: true)
return team unless team.valid?
- plaintext_team_password = Crypto::Symmetric::Aes256.random_key
+ plaintext_team_password = team.new_team_password
team.add_user(owner, plaintext_team_password)
team
diff --git a/app/models/team/shared.rb b/app/models/team/shared.rb
index ad467413e..33bf7ca84 100644
--- a/app/models/team/shared.rb
+++ b/app/models/team/shared.rb
@@ -20,7 +20,7 @@ def create(creator, params)
team = super(params)
return team unless team.valid?
- plaintext_team_password = Crypto::Symmetric::Aes256.random_key
+ plaintext_team_password = team.new_team_password
team.add_user(creator, plaintext_team_password)
unless team.private?
User::Human.admins.each do |a|
diff --git a/app/models/teammember.rb b/app/models/teammember.rb
index 6d1559a05..d9092719b 100644
--- a/app/models/teammember.rb
+++ b/app/models/teammember.rb
@@ -35,12 +35,10 @@ class Teammember < ApplicationRecord
scope :in_private_teams, (-> { joins(:team).where('teams.private' => true) })
- def recrypt_team_password(user, admin, private_key)
- teammember_admin = admin.teammembers.find_by(team_id: team_id)
- team_password = Crypto::Rsa.decrypt(teammember_admin.
- password, private_key)
-
- self.password = Crypto::Rsa.encrypt(team_password, user.public_key)
+ def reset_team_password(new_team_password)
+ public_key = user.public_key
+ encrypted_team_password = Crypto::Rsa.encrypt(new_team_password, public_key)
+ self.encrypted_team_password = encrypted_team_password
save!
end
diff --git a/app/models/user/human.rb b/app/models/user/human.rb
index c21ba5740..40d7c145a 100644
--- a/app/models/user/human.rb
+++ b/app/models/user/human.rb
@@ -181,7 +181,7 @@ def empower(actor, private_key)
next if t.teammember?(self)
active_teammember = t.teammembers.find_by user_id: actor.id
- team_password = Crypto::Rsa.decrypt(active_teammember.password, private_key)
+ team_password = Crypto::Rsa.decrypt(active_teammember.encrypted_team_password, private_key)
t.add_user(self, team_password)
end
end
diff --git a/app/serializers/team_serializer.rb b/app/serializers/team_serializer.rb
index a10864b1d..10889a912 100644
--- a/app/serializers/team_serializer.rb
+++ b/app/serializers/team_serializer.rb
@@ -16,7 +16,8 @@
class TeamSerializer < ApplicationSerializer
# To hide STI name in Frontend
type Team.name.pluralize
- attributes :id, :name, :description, :private, :favourised, :deletable, :type
+ attributes :id, :name, :description, :private, :favourised, :deletable, :type,
+ :encryption_algorithm, :password_bitsize
has_many :folders, serializer: FolderSerializer
@@ -31,4 +32,8 @@ def deletable
def personal_team
object.personal_team?
end
+
+ def password_bitsize
+ object.encryption_class.password_bitsize
+ end
end
diff --git a/app/utils/crypto/symmetric.rb b/app/utils/crypto/symmetric.rb
index 5e243935d..23de60fb5 100644
--- a/app/utils/crypto/symmetric.rb
+++ b/app/utils/crypto/symmetric.rb
@@ -3,7 +3,16 @@
require 'openssl'
require 'digest/sha1'
-class Crypto::Symmetric
+class ::Crypto::Symmetric
+ class_attribute :password_bitsize
+
+ LATEST_ALGORITHM = 'AES256IV'
+
+ # Add further algorithms at the bottom
+ ALGORITHMS = {
+ AES256: ::Crypto::Symmetric::Aes256,
+ AES256IV: ::Crypto::Symmetric::Aes256iv
+ }.with_indifferent_access.freeze
class << self
@@ -18,5 +27,9 @@ def decrypt
def random_key
raise 'Implement in subclass'
end
+
+ def latest_algorithm?(entry)
+ LATEST_ALGORITHM == entry.encryption_algorithm
+ end
end
end
diff --git a/app/utils/crypto/symmetric/aes256.rb b/app/utils/crypto/symmetric/aes256.rb
index 48d5a277c..ec30fe44c 100644
--- a/app/utils/crypto/symmetric/aes256.rb
+++ b/app/utils/crypto/symmetric/aes256.rb
@@ -3,34 +3,37 @@
require 'openssl'
require 'digest/sha1'
-require_relative './aes256'
+class ::Crypto::Symmetric::Aes256 < ::Crypto::Symmetric
-class Crypto::Symmetric::Aes256 < Crypto::Symmetric
CIPHER ||= 'AES-256-CBC'
MAGIC ||= 'Salted__'
SALT_LENGTH ||= 8
ITERATION_COUNT ||= 1000
- class << self
+ self.password_bitsize = OpenSSL::Cipher.new(CIPHER).key_len * 8
+ class << self
def encrypt(data, key)
cipher = cipher_encrypt_mode
# set encryption key
cipher.key = key
- # return encrypted data
- cipher.update(data) + cipher.final
+ # encrypt given data
+ encrypted_data = cipher.update(data) + cipher.final
+
+ # return data and nil iv value
+ { data: encrypted_data, iv: nil }
end
- def decrypt(data, key)
+ def decrypt(encrypted_data, key)
cipher = cipher_decrypt_mode
# set decryption key
cipher.key = key
# decrypt data
- cipher.update(data) + cipher.final
+ cipher.update(encrypted_data[:data]) + cipher.final
end
def encrypt_with_salt(data, key)
diff --git a/app/utils/crypto/symmetric/aes256iv.rb b/app/utils/crypto/symmetric/aes256iv.rb
index fddb63c21..29104f1ad 100644
--- a/app/utils/crypto/symmetric/aes256iv.rb
+++ b/app/utils/crypto/symmetric/aes256iv.rb
@@ -3,9 +3,7 @@
require 'openssl'
require 'digest/sha1'
-require_relative './aes256'
-
-class Crypto::Symmetric::Aes256iv < Crypto::Symmetric::Aes256
+class ::Crypto::Symmetric::Aes256iv < ::Crypto::Symmetric::Aes256
class << self
@@ -19,17 +17,17 @@ def encrypt(data, key)
# encrypt given data
encrypted_data = cipher.update(data) + cipher.final
- [encrypted_data, iv]
+ { data: encrypted_data, iv: iv }
end
- def decrypt(data, key, iv)
+ def decrypt(encrypted_data, key)
cipher = cipher_decrypt_mode
cipher.key = key
- cipher.iv = iv
+ cipher.iv = encrypted_data[:iv]
- # decrypt data
- cipher.update(data) + cipher.final
+ # decrypt given data
+ cipher.update(encrypted_data[:data]) + cipher.final
end
end
end
diff --git a/app/utils/crypto/symmetric/recrypt.rb b/app/utils/crypto/symmetric/recrypt.rb
new file mode 100644
index 000000000..73be58abe
--- /dev/null
+++ b/app/utils/crypto/symmetric/recrypt.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+class Crypto::Symmetric::Recrypt
+
+ def initialize(current_user, team, private_key)
+ @current_user = current_user
+ @team = team
+ @private_key = private_key
+ end
+
+ def perform
+ return if already_recrypted? || recrypt_locked?
+
+ @team.recrypt_in_progress!
+ @team_password = @team.decrypt_team_password(@current_user, @private_key)
+ @new_team_password = @team.new_team_password
+
+ begin
+ recrypt
+ rescue => e # rubocop:disable Style/RescueStandardError
+ @team.recrypt_failed!
+ raise "Recrypt failed: #{e.message}"
+ end
+ end
+
+ private
+
+ def already_recrypted?
+ Crypto::Symmetric.latest_algorithm?(@team)
+ end
+
+ def recrypt_locked?
+ @team.recrypt_in_progress? || @team.recrypt_failed?
+ end
+
+ def recrypt
+ ActiveRecord::Base.transaction do
+ @team.encryptables.find_each do |encryptable|
+ encryptable.recrypt(@team_password, @new_team_password, latest_encryption_class)
+ end
+
+ update_team
+ end
+ end
+
+ def update_team
+ @team.teammembers.find_each do |member|
+ member.reset_team_password(@new_team_password)
+ end
+
+ @team.encryption_algorithm = ::Crypto::Symmetric::LATEST_ALGORITHM
+ @team.recrypt_done!
+ end
+
+ def latest_encryption_class
+ encryption_algorithm = ::Crypto::Symmetric::LATEST_ALGORITHM
+ Crypto::Symmetric::ALGORITHMS[encryption_algorithm]
+ end
+
+end
diff --git a/app/utils/encryptable_transfer.rb b/app/utils/encryptable_transfer.rb
index 675340522..f0fdef4e0 100644
--- a/app/utils/encryptable_transfer.rb
+++ b/app/utils/encryptable_transfer.rb
@@ -3,18 +3,12 @@
class EncryptableTransfer
def transfer(encryptable, receiver, sender)
- transfer_password = new_transfer_password
- encryptable.encrypt(transfer_password)
+ encryption_algorithm = receiver_encryption_algorithm(receiver)
- encryptable.name = encryptable_destination_name(encryptable, receiver)
+ transfer_password = encryption_algorithm.random_key
+ encryptable.encrypt(transfer_password, encryption_algorithm)
- encryptable.update!(
- folder: receiver.inbox_folder,
- sender_id: sender.id,
- encrypted_transfer_password:
- Base64.encode64(encrypted_transfer_password(transfer_password, receiver))
- )
- encryptable
+ update_encryptable(encryptable, receiver, sender, transfer_password)
end
def receive(encryptable, private_key, personal_team_password)
@@ -31,6 +25,18 @@ def receive(encryptable, private_key, personal_team_password)
private
+ def update_encryptable(encryptable, receiver, sender, transfer_password)
+ encryptable.name = encryptable_destination_name(encryptable, receiver)
+
+ encryptable.update!(
+ folder: receiver.inbox_folder,
+ sender_id: sender.id,
+ encrypted_transfer_password:
+ Base64.encode64(encrypted_transfer_password(transfer_password, receiver))
+ )
+ encryptable
+ end
+
def encryptable_destination_name(encryptable, receiver)
existing_names = receiver.inbox_folder.encryptables.pluck(:name)
is_file = encryptable.is_a?(Encryptable::File)
@@ -45,8 +51,9 @@ def encrypted_transfer_password(password, receiver)
)
end
- def new_transfer_password
- Crypto::Symmetric::Aes256.random_key
+ def receiver_encryption_algorithm(receiver)
+ encryption_algorithm = receiver.personal_team.encryption_algorithm
+ Crypto::Symmetric::ALGORITHMS[encryption_algorithm]
end
def transfered_name(name, existing_names, is_file)
diff --git a/db/migrate/20220517131300_change_tables_to_support_recrypt.rb b/db/migrate/20220517131300_change_tables_to_support_recrypt.rb
new file mode 100644
index 000000000..6bb15e2ac
--- /dev/null
+++ b/db/migrate/20220517131300_change_tables_to_support_recrypt.rb
@@ -0,0 +1,8 @@
+class ChangeTablesToSupportRecrypt < ActiveRecord::Migration[7.0]
+ def change
+ add_column :teams, :recrypt_state, :integer, default: Team.recrypt_states[:done], null: false
+ add_column :teams, :encryption_algorithm, :string
+
+ Team.update_all(encryption_algorithm: 'AES256')
+ end
+end
diff --git a/db/migrate/20220609063817_rename_password_to_encrypted_team_password.rb b/db/migrate/20220609063817_rename_password_to_encrypted_team_password.rb
new file mode 100644
index 000000000..301f517a5
--- /dev/null
+++ b/db/migrate/20220609063817_rename_password_to_encrypted_team_password.rb
@@ -0,0 +1,5 @@
+class RenamePasswordToEncryptedTeamPassword < ActiveRecord::Migration[7.0]
+ def change
+ rename_column :teammembers, :password, :encrypted_team_password
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 4cc966821..40e3c98f2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -49,7 +49,7 @@
create_table "teammembers", force: :cascade do |t|
t.integer "team_id", default: 0, null: false
- t.binary "password", null: false
+ t.binary "encrypted_team_password", null: false
t.integer "user_id", default: 0, null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
@@ -64,6 +64,8 @@
t.boolean "private", default: false, null: false
t.string "type", default: "Team::Shared", null: false
t.integer "personal_owner_id"
+ t.integer "recrypt_state", default: 1, null: false
+ t.string "encryption_algorithm"
t.index ["name"], name: "index_teams_on_name"
end
diff --git a/db/seeds/support/team_folders_encryptables_seeder.rb b/db/seeds/support/team_folders_encryptables_seeder.rb
index 39c45e10b..e72a1d67c 100644
--- a/db/seeds/support/team_folders_encryptables_seeder.rb
+++ b/db/seeds/support/team_folders_encryptables_seeder.rb
@@ -14,7 +14,7 @@ def seed_team(name, members, admin = false)
seed_folder(team)
end
- plaintext_team_pw = Crypto::Symmetric::Aes256.random_key
+ plaintext_team_pw = Crypto::Symmetric::Aes256iv.random_key
members.each do |m|
u = user(m)
diff --git a/frontend/app/components/encryptable/show.js b/frontend/app/components/encryptable/show.js
index 96adf1adf..202b485e2 100644
--- a/frontend/app/components/encryptable/show.js
+++ b/frontend/app/components/encryptable/show.js
@@ -5,6 +5,7 @@ import { inject as service } from "@ember/service";
export default class ShowComponent extends Component {
@service router;
+ @service navService;
constructor() {
super(...arguments);
diff --git a/frontend/app/components/team/index.js b/frontend/app/components/team/index.js
new file mode 100644
index 000000000..8ab570625
--- /dev/null
+++ b/frontend/app/components/team/index.js
@@ -0,0 +1,15 @@
+import Component from "@glimmer/component";
+import { inject as service } from "@ember/service";
+import { tracked } from "@glimmer/tracking";
+
+export default class Index extends Component {
+ @service navService;
+ @service loading;
+
+ @tracked model = this.args.model;
+ @tracked q = this.args.q;
+
+ constructor() {
+ super(...arguments);
+ }
+}
diff --git a/frontend/app/controllers/teams/index.js b/frontend/app/controllers/teams/index.js
new file mode 100644
index 000000000..1a03fc946
--- /dev/null
+++ b/frontend/app/controllers/teams/index.js
@@ -0,0 +1,6 @@
+import { inject as service } from "@ember/service";
+import ApplicationController from "../application";
+
+export default class TeamsIndexController extends ApplicationController {
+ @service loading;
+}
diff --git a/frontend/app/models/team.js b/frontend/app/models/team.js
index 1cb4b1130..004cea361 100644
--- a/frontend/app/models/team.js
+++ b/frontend/app/models/team.js
@@ -4,6 +4,8 @@ export default class Team extends Model {
@attr("string") name;
@attr("string") description;
@attr("string") type;
+ @attr("string") encryptionAlgorithm;
+ @attr("number") passwordBitsize;
@attr("boolean") private;
@attr("boolean") favourised;
@attr("boolean") deletable;
diff --git a/frontend/app/routes/teams/show.js b/frontend/app/routes/teams/show.js
index 78fba43b4..fe150094a 100644
--- a/frontend/app/routes/teams/show.js
+++ b/frontend/app/routes/teams/show.js
@@ -8,6 +8,7 @@ export default class TeamsShowRoute extends BaseRoute {
@service intl;
templateName = "teams/index";
+ controllerName = "teams/index";
afterModel(_resolvedModel, transition) {
this.navService.setSelectedTeamById(transition.to.params.team_id);
diff --git a/frontend/app/styles/encryptable-show.scss b/frontend/app/styles/encryptable-show.scss
index a81fda9d8..416f15c42 100644
--- a/frontend/app/styles/encryptable-show.scss
+++ b/frontend/app/styles/encryptable-show.scss
@@ -126,3 +126,9 @@
justify-content: center;
}
}
+
+.encryptable-lock-icon {
+ border: 0;
+ margin-left: 15px;
+ margin-top: 7px;
+}
diff --git a/frontend/app/templates/components/encryptable/attribute-field.hbs b/frontend/app/templates/components/encryptable/attribute-field.hbs
index 07bfea2ad..e0b29a5e1 100644
--- a/frontend/app/templates/components/encryptable/attribute-field.hbs
+++ b/frontend/app/templates/components/encryptable/attribute-field.hbs
@@ -7,14 +7,22 @@
{{/if}}
{{/unless}}
-
- {{#if this.isAttributeVisible}}
-
- {{else}}
-
{{t (concat "encryptable/credentials.show.show_" this.args.attribute)}}
- {{/if}}
-
+
+
+ {{#unless this.args.row}}
+
+
+
+
+ {{/unless}}
diff --git a/frontend/app/templates/components/encryptable/form.hbs b/frontend/app/templates/components/encryptable/form.hbs
index 654833e5b..8e21862ec 100644
--- a/frontend/app/templates/components/encryptable/form.hbs
+++ b/frontend/app/templates/components/encryptable/form.hbs
@@ -111,7 +111,7 @@
{{!-- Bind Popper to modal with viewportSelector, more information: https://www.ember-bootstrap.com/api/classes/Components.Tooltip.html#property_viewportPadding--}}
-
+
diff --git a/frontend/app/templates/teams/index.hbs b/frontend/app/templates/teams/index.hbs
index 50c24f406..ca2d8e893 100644
--- a/frontend/app/templates/teams/index.hbs
+++ b/frontend/app/templates/teams/index.hbs
@@ -1,14 +1,22 @@
- {{#if this.q}}
-
- {{/if}}
- {{#if @model}}
- {{#each this.model as |team|}}
-
- {{/each}}
+ {{#if this.loading.isLoading}}
+
{{else}}
-
{{t "teams.index.no_content"}}
+ {{#if this.q}}
+
+ {{/if}}
+ {{#if @model}}
+ {{#each this.model as |team|}}
+
+ {{/each}}
+ {{else}}
+
{{t "teams.index.no_content"}}
+ {{/if}}
{{/if}}
diff --git a/frontend/package.json b/frontend/package.json
index 99e211a55..277524350 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -57,6 +57,7 @@
"ember-in-viewport": "^3.9.0",
"ember-intl": "^5.7.2",
"ember-load-initializers": "^2.1.2",
+ "ember-loading": "^2.0.0",
"ember-moment": "^9.0.1",
"ember-notify": "^6.0.2",
"ember-power-select": "^4.0.3",
diff --git a/frontend/public/assets/images/encrypted_small.svg b/frontend/public/assets/images/encrypted_small.svg
index 00bbc319b..302de567c 100644
--- a/frontend/public/assets/images/encrypted_small.svg
+++ b/frontend/public/assets/images/encrypted_small.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/frontend/public/assets/images/not_encrypted_small.svg b/frontend/public/assets/images/not_encrypted_small.svg
index cec092a9f..50c713b3f 100644
--- a/frontend/public/assets/images/not_encrypted_small.svg
+++ b/frontend/public/assets/images/not_encrypted_small.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/frontend/tests/integration/components/encryptable/row-test.js b/frontend/tests/integration/components/encryptable/row-test.js
index 808e7e066..b6a11963d 100644
--- a/frontend/tests/integration/components/encryptable/row-test.js
+++ b/frontend/tests/integration/components/encryptable/row-test.js
@@ -62,6 +62,9 @@ module("Integration | Component | encryptable/row", function (hooks) {
assert.dom(this.element.querySelector("#email-field")).doesNotExist();
assert.dom(this.element.querySelector("#token-field")).doesNotExist();
assert.dom(this.element.querySelector("#custom-attr-field")).doesNotExist();
+ assert
+ .dom(this.element.querySelector(".encryptable-lock-icon"))
+ .doesNotExist();
});
test("it renders with two set attribute", async function (assert) {
@@ -107,6 +110,9 @@ module("Integration | Component | encryptable/row", function (hooks) {
assert.dom(this.element.querySelector("#show-email")).doesNotExist();
assert.dom(this.element.querySelector("#show-token")).doesNotExist();
assert.dom(this.element.querySelector("#show-customAttr")).doesNotExist();
+ assert
+ .dom(this.element.querySelector(".encryptable-lock-icon"))
+ .doesNotExist();
});
test("it renders with three or more set attribute", async function (assert) {
@@ -147,6 +153,9 @@ module("Integration | Component | encryptable/row", function (hooks) {
assert.dom(this.element.querySelector("#email-field")).doesNotExist();
assert.dom(this.element.querySelector("#token-field")).doesNotExist();
assert.dom(this.element.querySelector("#custom-attr-field")).doesNotExist();
+ assert
+ .dom(this.element.querySelector(".encryptable-lock-icon"))
+ .doesNotExist();
});
test("it renders encryptable row for transferred file", async function (assert) {
diff --git a/frontend/tests/integration/components/encryptable/show-test.js b/frontend/tests/integration/components/encryptable/show-test.js
index be1b8f132..8c2c47069 100644
--- a/frontend/tests/integration/components/encryptable/show-test.js
+++ b/frontend/tests/integration/components/encryptable/show-test.js
@@ -74,6 +74,11 @@ module("Integration | Component | encryptable/show", function (hooks) {
.doesNotExist();
assert.dom(this.element.querySelector("#show-customAttr")).doesNotExist();
+ let encryption_algorithm = this.element.querySelector(
+ ".encryptable-lock-icon"
+ );
+ assert.ok(isPresent(encryption_algorithm));
+
await click("#show-password");
assert.equal(
@@ -131,6 +136,11 @@ module("Integration | Component | encryptable/show", function (hooks) {
"Show custom attribute"
);
+ let encryption_algorithm = this.element.querySelector(
+ ".encryptable-lock-icon"
+ );
+ assert.ok(isPresent(encryption_algorithm));
+
await click("#show-token");
assert.equal(this.element.querySelector("#cleartext_token").value, "token");
@@ -236,6 +246,11 @@ module("Integration | Component | encryptable/show", function (hooks) {
this.element.querySelector("#encryptable-file-actions").innerText,
"Actions"
);
+
+ let encryption_algorithm = this.element.querySelector(
+ ".encryptable-lock-icon"
+ );
+ assert.ok(isPresent(encryption_algorithm));
});
test("should render all german translations and encryptable values", async function (assert) {
@@ -327,6 +342,11 @@ module("Integration | Component | encryptable/show", function (hooks) {
this.element.querySelector("#encryptable-file-actions").innerText,
"Aktionen"
);
+
+ let encryption_algorithm = this.element.querySelector(
+ ".encryptable-lock-icon"
+ );
+ assert.ok(isPresent(encryption_algorithm));
});
test("should render all swiss german translations and encryptable values", async function (assert) {
@@ -418,6 +438,11 @@ module("Integration | Component | encryptable/show", function (hooks) {
this.element.querySelector("#encryptable-file-actions").innerText,
"Aktionä"
);
+
+ let encryption_algorithm = this.element.querySelector(
+ ".encryptable-lock-icon"
+ );
+ assert.ok(isPresent(encryption_algorithm));
});
test("should render all french translations and encryptable values", async function (assert) {
@@ -509,6 +534,11 @@ module("Integration | Component | encryptable/show", function (hooks) {
this.element.querySelector("#encryptable-file-actions").innerText,
"Actions"
);
+
+ let encryption_algorithm = this.element.querySelector(
+ ".encryptable-lock-icon"
+ );
+ assert.ok(isPresent(encryption_algorithm));
});
test("it renders a transferred encryptable file", async function (assert) {
@@ -534,6 +564,10 @@ module("Integration | Component | encryptable/show", function (hooks) {
assert.ok(text.includes("Download file"));
assert.ok(text.includes("Sender name: Bob Beier"));
+ assert
+ .dom(this.element.querySelector(".encryptable-lock-icon"))
+ .doesNotExist();
+
let deleteButton = this.element.querySelector('.icon-button[alt="delete"]');
assert.ok(isPresent(deleteButton));
});
diff --git a/frontend/tests/integration/components/team/show-test.js b/frontend/tests/integration/components/team/show-test.js
index dc2658942..827435442 100644
--- a/frontend/tests/integration/components/team/show-test.js
+++ b/frontend/tests/integration/components/team/show-test.js
@@ -43,6 +43,7 @@ module("Integration | Component | team/show", function (hooks) {
name: "BBT",
description: "Berufsbildungsteam of Puzzle ITC",
folders: [folder],
+ encryptionAlgorithm: "AES256",
userFavouriteTeams: [{ favourised: true }]
});
diff --git a/frontend/translations/ch_be.yml b/frontend/translations/ch_be.yml
index dec73bef9..d39b95db2 100644
--- a/frontend/translations/ch_be.yml
+++ b/frontend/translations/ch_be.yml
@@ -111,7 +111,6 @@ ch_be:
new:
title: Nöi Zuägangsdate
form:
- encryptedField: Das Fäld wird verschlüsslät
notEncryptedField: Das Fäld wird nid verschlüsslät
row:
clickToSeeAttrs: Klick wenn aui Attribut möchtisch gseh
@@ -387,6 +386,7 @@ ch_be:
delete_encryptables: Zuägangsdate lösche
configure: Konfigurier d'Mitgliedr
sent_by: Gsändet vo
+ encryption_algorithm: "Verschlüsslet mit "
helpers:
label:
diff --git a/frontend/translations/de.yml b/frontend/translations/de.yml
index d6942978e..bd8d4ea85 100644
--- a/frontend/translations/de.yml
+++ b/frontend/translations/de.yml
@@ -111,7 +111,6 @@ de:
new:
title: Neue Zugangsdaten
form:
- encryptedField: Dieses Feld wird verschlüsselt
notEncryptedField: Dieses Feld wird nicht verschlüsselt
row:
clickToSeeAttrs: Klicke um alle Attribute zu sehen
@@ -387,6 +386,7 @@ de:
delete_encryptables: Zugangsdaten löschen
configure: Konfiguriere Mitglieder
sent_by: Gesendet von
+ encryption_algorithm: "Verschlüsselt mit "
helpers:
label:
diff --git a/frontend/translations/en.yml b/frontend/translations/en.yml
index 9c9d03be2..fc7826ee8 100644
--- a/frontend/translations/en.yml
+++ b/frontend/translations/en.yml
@@ -112,7 +112,6 @@ en:
new:
title: New Credentials
form:
- encryptedField: This field is encrypted
notEncryptedField: This field is not encrypted
row:
clickToSeeAttrs: Click to see all attributes
@@ -387,6 +386,7 @@ en:
delete_encryptables: Delete the Credentials
configure: Configure Members
sent_by: Sent by
+ encryption_algorithm: "Encrypted with "
helpers:
label:
diff --git a/frontend/translations/fr.yml b/frontend/translations/fr.yml
index 8c6383af5..5370cc929 100644
--- a/frontend/translations/fr.yml
+++ b/frontend/translations/fr.yml
@@ -112,7 +112,6 @@ fr:
new:
title: Nouveau compte
form:
- encryptedField: Ce champ est crypté
notEncryptedField: Ce champ n'est pas crypté
row:
clickToSeeAttrs: Cliquez pour voir tous les attributs
@@ -388,6 +387,7 @@ fr:
delete_encryptables: Supprimer le compte
configure: Configurer les membres
sent_by: Envoyé par
+ encryption_algorithm: "Crypté avec "
helpers:
label:
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index c930bb317..d838a0a51 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -514,16 +514,16 @@
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af"
integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==
+"@babel/helper-plugin-utils@^7.10.1", "@babel/helper-plugin-utils@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295"
+ integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
+
"@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7":
version "7.16.7"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5"
integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==
-"@babel/helper-plugin-utils@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295"
- integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
-
"@babel/helper-remap-async-to-generator@^7.13.0":
version "7.13.0"
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz#376a760d9f7b4b2077a9dd05aa9c3927cadb2209"
@@ -2186,6 +2186,15 @@
"@babel/helper-validator-identifier" "^7.14.0"
to-fast-properties "^2.0.0"
+"@babel/types@^7.10.2", "@babel/types@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
+ integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==
+ dependencies:
+ "@babel/helper-string-parser" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.5"
+ to-fast-properties "^2.0.0"
+
"@babel/types@^7.12.1", "@babel/types@^7.13.0", "@babel/types@^7.13.16", "@babel/types@^7.14.1", "@babel/types@^7.4.4":
version "7.14.4"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.4.tgz#bfd6980108168593b38b3eb48a24aa026b919bc0"
@@ -2202,15 +2211,6 @@
"@babel/helper-validator-identifier" "^7.16.7"
to-fast-properties "^2.0.0"
-"@babel/types@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
- integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==
- dependencies:
- "@babel/helper-string-parser" "^7.22.5"
- "@babel/helper-validator-identifier" "^7.22.5"
- to-fast-properties "^2.0.0"
-
"@cnakazawa/watch@^1.0.3":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
@@ -7675,6 +7675,17 @@ ember-compatibility-helpers@^1.2.4, ember-compatibility-helpers@^1.2.5:
fs-extra "^9.1.0"
semver "^5.4.1"
+ember-concurrency-async@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ember-concurrency-async/-/ember-concurrency-async-1.0.0.tgz#635ec2b7b11c083699801b85c5bb757bb7ebfd45"
+ integrity sha512-otE1UcF+VYva8qdkYayHVBrGDG+Lt9oYLLMt3heEo98Mv9abdjrdaLzvSMMspzI3ncgKtmZsEwn+aubvq+Zhhw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.1"
+ "@babel/types" "^7.10.2"
+ ember-cli-babel "^7.19.0"
+ ember-cli-babel-plugin-helpers "^1.1.1"
+ ember-cli-htmlbars "^4.3.1"
+
ember-concurrency-decorators@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/ember-concurrency-decorators/-/ember-concurrency-decorators-2.0.3.tgz#2816c9a0283b90ba5340fc5b4e0b92ea91f7d6e3"
@@ -7685,6 +7696,14 @@ ember-concurrency-decorators@^2.0.0:
ember-cli-htmlbars "^4.3.1"
ember-cli-typescript "^3.1.4"
+ember-concurrency-ts@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/ember-concurrency-ts/-/ember-concurrency-ts-0.3.1.tgz#0b3b524a6a96c8ab749b20e1d4da00569773567a"
+ integrity sha512-lE9uqPgK1Y9PN/0BJ5zE2a+h95izRCn6FCyt7qVV3012TlblTynsBaoUuAbN1T3KfzFsrJaXwsxzRbDjEde2Sw==
+ dependencies:
+ ember-cli-babel "^7.19.0"
+ ember-cli-htmlbars "^4.3.1"
+
"ember-concurrency@>=1.0.0 <3":
version "2.1.0"
resolved "https://registry.yarnpkg.com/ember-concurrency/-/ember-concurrency-2.1.0.tgz#5e55c19f43fb245c4fbe0628cbf26cc6561af40c"
@@ -7696,7 +7715,7 @@ ember-concurrency-decorators@^2.0.0:
ember-compatibility-helpers "^1.2.0"
ember-destroyable-polyfill "^2.0.2"
-"ember-concurrency@>=1.3.0 <3":
+"ember-concurrency@>=1.3.0 <3", ember-concurrency@^2.0.3:
version "2.3.7"
resolved "https://registry.yarnpkg.com/ember-concurrency/-/ember-concurrency-2.3.7.tgz#52d786e37704b9054da1952638797e23714ec0e1"
integrity sha512-sz6sTIXN/CuLb5wdpauFa+rWXuvXXSnSHS4kuNzU5GSMDX1pLBWSuovoUk61FUe6CYRqBmT1/UushObwBGickQ==
@@ -7881,6 +7900,18 @@ ember-load-initializers@^2.1.2:
ember-cli-babel "^7.13.0"
ember-cli-typescript "^2.0.2"
+ember-loading@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ember-loading/-/ember-loading-2.0.0.tgz#49cdbed83b4ef29be00d28e5a532a72113233b31"
+ integrity sha512-aGFZszIwmrIZ5XINv9TXQGWrfpKIiPwYiakEmRXx0Jvr5ZnUyKtCO84+FaKMyezrbDWsq0UjYqmdiqSAXhIkIA==
+ dependencies:
+ ember-cli-babel "^7.26.6"
+ ember-cli-htmlbars "^5.7.1"
+ ember-cli-typescript "^4.1.0"
+ ember-concurrency "^2.0.3"
+ ember-concurrency-async "^1.0.0"
+ ember-concurrency-ts "^0.3.0"
+
ember-maybe-in-element@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/ember-maybe-in-element/-/ember-maybe-in-element-2.0.3.tgz#640ea56b492bdacd1c41c128c2163d933c18c3ec"
diff --git a/public/CHANGELOG.md b/public/CHANGELOG.md
index c33953c9c..98002e55f 100644
--- a/public/CHANGELOG.md
+++ b/public/CHANGELOG.md
@@ -1,5 +1,9 @@
+## Version 5.2
+- Recrypt encrypted db data with AES256iv
+
## Version 5.1
- Introduce Encryptable Credentials Sharing
+- Introduce ability to dynamically add new Encryption Alogrithms
## Version 5.0
- Introduce new Attributes for Credentials
diff --git a/spec/controllers/api/encryptables_controller_spec.rb b/spec/controllers/api/encryptables_controller_spec.rb
index cf603457b..87af8811f 100644
--- a/spec/controllers/api/encryptables_controller_spec.rb
+++ b/spec/controllers/api/encryptables_controller_spec.rb
@@ -23,7 +23,6 @@
end
let(:credentials1) { encryptables(:credentials1) }
let(:file1) { encryptables(:file1) }
- let(:transferred_file1) { encryptables(:transferredFile1) }
context 'GET index' do
@@ -61,7 +60,7 @@
credentials1_json_attributes = credentials1_json['attributes']
credentials1_json_relationships = credentials1_json['relationships']
- expect(data.count).to eq 2
+ expect(data.count).to eq 1
expect(credentials1_json_attributes['name']).to eq credentials1.name
expect(credentials1_json['id']).to eq credentials1.id.to_s
expect(credentials1_json_attributes['cleartext_username']).to be_nil
@@ -86,7 +85,7 @@
credentials1_json_attributes = credentials1_json['attributes']
credentials1_json_relationships = credentials1_json['relationships']
- expect(data.count).to eq 2
+ expect(data.count).to eq 1
expect(credentials1_json_attributes['name']).to eq credentials1.name
expect(credentials1_json['id']).to eq credentials1.id.to_s
expect(credentials1_json_attributes['cleartext_username']).to be_nil
@@ -764,32 +763,58 @@
expect(received_file.cleartext_file).to eq('certificate')
end
- it 'download transferred encryptable' do
- login_as(:bob)
+ context 'recrypt' do
+ it 'download transferred encryptable old encryption algorithm' do
+ login_as(:bob)
- encryptable_file = prepare_transferred_encryptable
+ encryptable_file = prepare_transferred_encryptable(Crypto::Symmetric::Aes256)
- login_as(:alice)
+ login_as(:alice)
+
+ expect(controller).to receive(:send_file).exactly(:once)
+
+ get :show, params: { id: encryptable_file.id }, xhr: true
+ end
+
+ it 'Does return encrpytable record and dont start download old encryption algorithm' do
+ login_as(:bob)
+
+ encryptable_file = prepare_transferred_encryptable(Crypto::Symmetric::Aes256)
+
+ login_as(:alice)
- expect(controller).to receive(:send_file).exactly(:once)
+ expect(controller).not_to receive(:send_file)
+ expect_any_instance_of(CrudController).to receive(:render_entry).exactly(:once)
- get :show, params: { id: encryptable_file.id }, xhr: true
+ get :show, params: { id: encryptable_file.id }, xhr: true
+ end
end
- it 'displays transferred encryptable and dont download it' do
- login_as(:bob)
+ context 'Most recent encryption algorithm' do
+ it 'downloads transferred encryptable encrypted with most recent algorithm' do
+ login_as(:bob)
- encryptable_file = prepare_transferred_encryptable
+ encryptable_file = prepare_transferred_encryptable(Crypto::Symmetric::Aes256iv)
- login_as(:alice)
+ login_as(:alice)
+
+ expect(controller).to receive(:send_file).exactly(:once)
+
+ get :show, params: { id: encryptable_file.id }, xhr: true
+ end
+
+ it 'Does return encrpytable record and not the file to download with most recent algorithm' do
+ login_as(:bob)
- expect(controller).not_to receive(:send_file)
- expect_any_instance_of(CrudController).to receive(:render_entry).exactly(:once)
+ encryptable_file = prepare_transferred_encryptable(Crypto::Symmetric::Aes256iv)
- get :show, params: { id: encryptable_file.id,
- encryptable: ActionController::Parameters.new({
- test: 1
- }).permit! }, xhr: true
+ login_as(:alice)
+
+ expect(controller).not_to receive(:send_file)
+ expect_any_instance_of(CrudController).to receive(:render_entry).exactly(:once)
+
+ get :show, params: { id: encryptable_file.id }, xhr: true
+ end
end
end
@@ -805,12 +830,13 @@ def create_file
file
end
- def prepare_transferred_encryptable
+ def prepare_transferred_encryptable(encryption_algorithm)
encryptable_file = Encryptable::File.new(name: 'file',
+ folder_id: alice.inbox_folder.id,
cleartext_file: file_fixture('test_file.txt').read,
content_type: 'text/plain')
- transfer_password = Crypto::Symmetric::Aes256.random_key
+ transfer_password = encryption_algorithm.random_key
encryptable_file.encrypt(transfer_password)
diff --git a/spec/controllers/api/teams_controller_spec.rb b/spec/controllers/api/teams_controller_spec.rb
index 8db35393d..fd282b0ec 100644
--- a/spec/controllers/api/teams_controller_spec.rb
+++ b/spec/controllers/api/teams_controller_spec.rb
@@ -14,6 +14,7 @@
let!(:team4) { Fabricate(:non_private_team) }
let(:bobs_private_key) { bob.decrypt_private_key('password') }
let!(:team3_user) { team3.teammembers.first.user }
+ let(:test_file) { FixturesHelper.read_file('test_file.txt') }
context 'GET index' do
it 'should get team for search term' do
@@ -217,8 +218,8 @@
expect(encryptables.last['attributes']['name']).to eq(filename1)
expect(encryptables.last['attributes']['name']).not_to eq(filename2)
- expect(encryptables.count).to be(3)
- expect(included.size).to be(4)
+ expect(encryptables.count).to be(2)
+ expect(included.size).to be(3)
end
it 'returns sender_name if transferred encryptable' do
@@ -267,6 +268,7 @@
team3_attributes['favourised'] = false
team3_attributes['deletable'] = false
team3_attributes['personal_team'] = false
+ team3_attributes['password_bitsize'] = 256
expect(team3_attributes).to include(attributes_team)
folder_relationships_length = data.first['relationships']['folders']['data'].size
@@ -381,6 +383,122 @@
end
end
end
+
+ context 'Recrypt' do
+ it 'triggers team recrypt if latest algorithm is not applied on team' do
+ admin = users(:admin)
+ login_as(:admin)
+ api_user = admin.api_users.create!
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256')
+
+ team = Fabricate(:non_private_team)
+
+ # Add api user to team
+ admins_private_key = admin.decrypt_private_key('password')
+ plaintext_team_password = team.decrypt_team_password(admin, admins_private_key)
+ team.add_user(api_user, plaintext_team_password)
+
+ expect(team.encryption_algorithm).to eq('AES256')
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256IV')
+
+ get :index, params: { team_id: team.id }, xhr: true
+
+ expect(response.status).to be(200)
+
+ team.reload
+ expect(team.encryption_algorithm).to eq('AES256IV')
+ end
+
+ it 'does not recrypt if latest algorithm' do
+ login_as(:bob)
+
+ get :index, params: { team_id: team1.id }, xhr: true
+
+ expect(team1.encryption_algorithm).to eq('AES256IV')
+
+ expect(response.status).to be(200)
+
+ team1.reload
+ expect(team1.encryption_algorithm).to eq('AES256IV')
+ end
+ end
+
+ context 'Receive transferred encryptables' do
+ it 'Receive method gets called to encrypt transferred encryptable' do
+ login_as(:bob)
+
+ Fabricate(
+ :transferred_file,
+ id_sender: alice.id,
+ receiver_inbox_folder: bob.inbox_folder,
+ receiver_pk: bob.public_key,
+ encryption_algorithm: Crypto::Symmetric::Aes256
+ )
+
+ expect_any_instance_of(EncryptableTransfer)
+ .to receive(:receive)
+ .exactly(1).times
+ .and_return(nil)
+
+ default_folder = Folder.new(name: 'default', team: personal_team_bob)
+
+ personal_team_bob.folders = [default_folder, bob.inbox_folder]
+
+ personal_team_bob.encryption_algorithm = 'AES256'
+ personal_team_bob.save!
+
+ expect do
+ get :index, params: { team_id: personal_team_bob.id }, xhr: true
+ end.to raise_error(RuntimeError)
+
+ end
+
+ it 'Receive method to encrypt transferred encryptable dont get called on recent algorithm' do
+ login_as(:bob)
+
+ Fabricate(
+ :transferred_file,
+ id_sender: alice.id,
+ receiver_inbox_folder: bob.inbox_folder,
+ receiver_pk: bob.public_key,
+ encryption_algorithm: Crypto::Symmetric::Aes256iv
+ )
+
+ expect_any_instance_of(EncryptableTransfer)
+ .not_to receive(:receive)
+ .and_return(nil)
+
+ default_folder = Folder.new(name: 'default', team: personal_team_bob)
+
+ personal_team_bob.folders = [default_folder, bob.inbox_folder]
+
+ get :index, params: { team_id: personal_team_bob.id }, xhr: true
+ end
+
+ it 'It does not receive encryptables in personal team if they are not transferred' do
+ login_as(:bob)
+
+ params = {}
+ params[:name] = 'Shopping Account'
+ params[:folder_id] = bob.inbox_folder.id
+ params[:type] = 'Encryptable::Credentials'
+ params[:cleartext_username] = 'username'
+ Encryptable::Credentials.new(params)
+
+ expect_any_instance_of(EncryptableTransfer)
+ .not_to receive(:receive)
+ .exactly(1).times
+ .and_return(nil)
+
+ default_folder = Folder.new(name: 'default', team: personal_team_bob)
+
+ personal_team_bob.folders = [default_folder, bob.inbox_folder]
+
+ get :index, params: { team_id: personal_team_bob.id }, xhr: true
+ end
+ end
end
context 'PUT update' do
diff --git a/spec/fabricators/encryptables/credentials_fabricator.rb b/spec/fabricators/encryptables/credentials_fabricator.rb
index f78acd1f5..e52163a71 100644
--- a/spec/fabricators/encryptables/credentials_fabricator.rb
+++ b/spec/fabricators/encryptables/credentials_fabricator.rb
@@ -5,12 +5,66 @@
# See the COPYING file at the top-level directory or at
# https://github.com/puzzle/cryptopus.
-Fabricator(:credential, from: 'Encryptable::Credentials') do
+Fabricator(:credential_all_attrs, from: 'Encryptable::Credentials') do
transient :team_password
name { Faker::Team.creature }
cleartext_username { Faker::Internet.user_name }
cleartext_password { Faker::Internet.password }
- before_create do |account, attrs|
- account.encrypt(attrs[:team_password])
+ cleartext_token { Faker::Internet.uuid }
+ cleartext_pin { Faker::Internet.ip_v4_address }
+ cleartext_email { Faker::Internet.email }
+ cleartext_custom_attr_label { Faker::Internet.user_name }
+ cleartext_custom_attr { Faker::Internet.password }
+ before_create do |encryptable, attrs|
+ encryptable.encrypt(attrs[:team_password])
+ end
+end
+
+Fabricator(:credential_one_attr, from: 'Encryptable::Credentials') do
+ transient :team_password
+ name { Faker::Team.creature }
+ cleartext_token { Faker::Internet.uuid }
+ before_create do |encryptable, attrs|
+ encryptable.encrypt(attrs[:team_password])
+ end
+end
+
+Fabricator(:credential_no_attr, from: 'Encryptable::Credentials') do
+ transient :team_password
+ name { Faker::Team.creature }
+ before_create do |encryptable, attrs|
+ encryptable.encrypt(attrs[:team_password])
+ end
+end
+
+Fabricator(:file, from: 'Encryptable::File') do
+ transient :team_password
+ name { Faker::File.file_name }
+ cleartext_file { Faker::Hacker.say_something_smart }
+ before_create do |encryptable, attrs|
+ encryptable.encrypt(attrs[:team_password])
+ end
+end
+
+Fabricator(:transferred_file, from: 'Encryptable::File') do
+ transient :id_sender, :receiver_inbox_folder, :receiver_pk, :encryption_algorithm
+
+ name { Faker::File.file_name }
+ cleartext_file { Faker::Hacker.say_something_smart }
+ folder { |attrs| attrs[:receiver_inbox_folder] }
+ sender_id { |attrs| attrs[:id_sender] }
+ type { Encryptable::File }
+
+ before_create do |encryptable, attrs|
+ transfer_password = attrs[:encryption_algorithm].random_key
+
+ encrypted_transfer_password = Crypto::Rsa.encrypt(
+ transfer_password,
+ attrs[:receiver_pk]
+ )
+
+ encryptable.encrypted_transfer_password = Base64.encode64(encrypted_transfer_password)
+ encryptable.encrypt(transfer_password, Crypto::Symmetric::Aes256iv)
+
end
end
diff --git a/spec/fabricators/teams_fabricator.rb b/spec/fabricators/teams_fabricator.rb
index 4631b198c..df8f67c27 100644
--- a/spec/fabricators/teams_fabricator.rb
+++ b/spec/fabricators/teams_fabricator.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative '../../app/utils/crypto/symmetric/aes256'
-
Fabricator(:non_private_team, from: :team) do |t|
t.name { Faker::App.name }
t.description { Faker::Hacker.say_something_smart }
@@ -9,13 +7,32 @@
t.private false
t.type Team::Shared
after_create do |team|
- team_password = Crypto::Symmetric::Aes256.random_key
+ team_password = team.new_team_password
+ team.add_user(Fabricate(:user), team_password)
+ User::Human.admins.each do |a|
+ team.add_user(a, team_password)
+ end
+ folder = Fabricate(:folder, team: team)
+ Fabricate(:credential_all_attrs, folder: folder, team_password: team_password)
+ end
+end
+
+Fabricator(:old_encryption_algo_team, from: :team) do |t|
+ t.name { Faker::App.name }
+ t.description { Faker::Hacker.say_something_smart }
+ t.visible true
+ t.private false
+ t.type Team::Shared
+ t.encryption_algorithm 'AES256'
+ after_create do |team|
+ team_password = team.new_team_password
team.add_user(Fabricate(:user), team_password)
User::Human.admins.each do |a|
team.add_user(a, team_password)
end
folder = Fabricate(:folder, team: team)
- Fabricate(:credential, folder: folder, team_password: team_password)
+ Fabricate(:credential_one_attr, folder: folder, team_password: team_password)
+ Fabricate(:credential_no_attr, folder: folder, team_password: team_password)
end
end
@@ -24,11 +41,12 @@
t.description { Faker::Hacker.say_something_smart }
t.visible true
t.private true
+ t.encryption_algorithm 'AES256IV'
t.type Team::Shared
after_create do |team|
- team_password = Crypto::Symmetric::Aes256.random_key
+ team_password = team.new_team_password
team.add_user(Fabricate(:user), team_password)
folder = Fabricate(:folder, team: team)
- Fabricate(:credential, folder: folder, team_password: team_password)
+ Fabricate(:credential_all_attrs, folder: folder, team_password: team_password)
end
end
diff --git a/spec/fixtures/encryptables.yml b/spec/fixtures/encryptables.yml
index 3046b38a8..2743926f7 100644
--- a/spec/fixtures/encryptables.yml
+++ b/spec/fixtures/encryptables.yml
@@ -23,8 +23,8 @@ credentials1:
name: Personal Mailbox
description: Mailprovider One
folder: folder1
- encrypted_data: '{"password":{"iv":null,"data":"pulO7xz5jDwUVQzbOqJzIw=="},"username":{"iv":null,"data":"0CkUu2Bd9eNB4OCuXVC3TA=="},"token":{"iv":null,"data":"s7L8uN3B82rE0jfxbZTBLA=="}
- ,"pin":{"iv":null,"data":"hxFbaVAiXsYU41KWAsguxw=="},"email":{"iv":null,"data":"iQAeALndU+eKpkGwGNDHgw=="},"custom_attr":{"iv":null, "label":"Access Code","data":"6qN+5x+eYPekkZB/mfpgBg=="}}'
+ encrypted_data: '{"password":{"iv":"H9hjp4QeXwag2Py5BbIUsw==","data":"vDItEQ+iQ1e55wcu9yPeSw=="},"username":{"iv":"ANa+aisVyKLEZs660fBa4w==","data":"Go6I8GJMejqRWS8QxfL+iA=="},"token":{"iv":"eVqNiT+wZXHy7FB8vl76kg==","data":"HQqUtWGazCQue+uTloDGyA=="}
+ ,"pin":{"iv":"80e9BgLcDlJzmitc+KydAQ==","data":"4uXc5coIBOQ2CYSLQOeu6A=="},"email":{"iv":"ybQu7D5HgofF2WKkfrmv9w==","data":"QNQRKGFpN49nLN0MImhp6A=="},"custom_attr":{"iv":"iC1hdqLGuzeGXHmXFP6qmQ==", "label":"Access Code","data":"Bz2mauB+jEbVinb6nPsoQQ=="}}'
sender_id: null
encrypted_transfer_password: null
@@ -33,7 +33,7 @@ credentials2:
name: Twitter Account
description: My personal twitter account
folder: folder2
- encrypted_data: '{"password":{"iv":null,"data":"X2i8woXXwIHew6zcnBws9Q=="},"username":{"iv":null,"data":"Kvkd66uUiNq4Gw4Yh7PvVg=="}}'
+ encrypted_data: '{"password":{"iv":"fY77ROMiOCbMrpxSMiciTA==","data":"MP70lYnYplRoNw0XfUAYIQ=="},"username":{"iv":"2vjsDqePJPuYCWSzn1+OSA==","data":"Y3Q7oUop9SuPhH79r6mTBA=="}}'
file1:
type: Encryptable::File
@@ -41,12 +41,4 @@ file1:
description: One-Time access codes
encryptable_credential: credentials1
content_type: 'text/plain'
- encrypted_data: '{"file":{"iv":null,"data":"FvJS9jooGEX1aXqB0iP7wB6h2YwO479OM+RpNmBlbORivbVPky0rR4u3lNLN+DGIL93gQAlVHDw1CZe9zDoTgSyxsQFflQwGk3DMDS9xhoQSJzTkBPBIb33j9H7WG37CQwdNNFnn/NExiBZb+9dbmHGqw8KWvRd3Xd/oSlTr6w/c0gz3UEYfhC5l6P3xnDc2"}}'
-
-transferred_file1:
- type: Encryptable::File
- name: message.txt
- description: Hello Alice here are xy
- folder: inbox_folder_alice
- content_type: 'text/plain'
- encrypted_data: '{"file":{"iv":null,"data":"FvJS9jooGEX1aXqB0iP7wB6h2YwO479OM+RpNmBlbORivbVPky0rR4u3lNLN+DGIL93gQAlVHDw1CZe9zDoTgSyxsQFflQwGk3DMDS9xhoQSJzTkBPBIb33j9H7WG37CQwdNNFnn/NExiBZb+9dbmHGqw8KWvRd3Xd/oSlTr6w/c0gz3UEYfhC5l6P3xnDc2"}}'
+ encrypted_data: '{"file":{"iv":"JYwyW8IlX8dGttecsI/ImA==","data":"wkx7Ep10Ofe626QW8faqu64bDoQQm6Lf7w4hHWRU/vtkv+DeMWaZoLnK5n0rb21H7b9KOnYLWKGgohOaBEHiS1I8wML7IAi+mDSXQGvpooFF6AsWRFBRJMpetRIATzwwxxf+3le4G+u7L3U4NUH/KKdX5NrGUcjk3Nq2/PdCo4jkpLGKJVTgy8mNUWomgguC"}}'
diff --git a/spec/fixtures/files/encryptables/legacy_ose_secret.encrypted_data b/spec/fixtures/files/encryptables/legacy_ose_secret.encrypted_data
new file mode 100644
index 000000000..ea6b9e601
--- /dev/null
+++ b/spec/fixtures/files/encryptables/legacy_ose_secret.encrypted_data
@@ -0,0 +1 @@
+9zUb++e6Pj7BLmCmetSwalSVvxXB2UmregR9Ldvu/NmkErDSRWck+RKjBoZWKHeSOeAeNl+tHRTlF4Q6jU5HECceAckWWPy7wWfCtZKrkss94CfJf68L8tHnAyfPnx9/VvNiomFWbUvc3IjvIDLwGXLRIn5HcAxbr+ryTYksT4EEKpRxVEihG96MrooPVFobg0/Ot/bs1tHAiYzjNoWPlBaBWzMzLP4rAvT54Lb0f5B3GZOvwmoZw7nxHP8Wy4ktH/IIQizH6In3Jk2meYsMbJyPEYvTr3g1c0IPxPURB6p+5VBe1ueDPs50YoNPz7E1L4anP3iAssIz7gZC+eUhYwwqfpewiZHLXFyWZoXXtW4UesSdVQWlV1Ih2jbV34LontH7NwlVmoXj8N6GIk4b2HqKfUkRsSE4furRlen5UEtfAPyoWsXWkmgqwKY2XfmcbIoO7d5XdGXEuMbSZsrCDUjHI+WF5JkXW7om0aJ5LehnCFvlwdN74NJWyosRKpnkKz/R+tcCinNJ9DYUeMZYSn+CPaJ2KqkMBjKjJgvy7/fOw3Du8IFVY+qsOubxnBi+gMFLdv7dTm5Y1MIN2hSZJFL3T810m/WUTAxd0wOQPinuRVpeNy4NoluNbdRkyWXIGx1Rev65k5CeR/bYnnlnoO6EmbA7/UukgpnQKHngL8ttHImV7LypqT6XZ7DGqb3bIJeR01mqNBOmGhP1LEQKEJNP2/UaRI1uvj28vOxKAaFjllsLuKb4fxk+dyxMfc/AFTOiDA2ld6Si+miBiLt+OumSz1fL6ijQpL0zghtNWnWk0VP4c++r3e/1YKvyJqwWA3aL+PyjTmu71WxR/yNwxEMjyp5UZVEjVGw+xZX3ZGUUK8vpnwpNHJMzGYjsi8aH5SCRMDhu98N0DXDbmlsmyKVpF8/Vl/BKn7nw4Xmfw7iM2YrnG7ulkPcTUno2KEwxydXFcKh4RpH49LJZLYoGhEzn/5Z/fS/LQBCkhfOt1fVHTCJWdyLkKPnXCxat0hby9VDAQ0MbeFUBZmsXEqukAI/7mKjrAq/vUsYKdcTl9ZOFvVcfdEkUFDsy5iv/uMghoA2dcFWLw0ehsosEvkHRoBEhyoY8nLW13WZl//Y1LWFgLg4EPUEbjGMGYXpF2op4F7+ahgtwbQS6jEtD9vBr0jUvurc2adDsru0IvVfdyAklhvtsVuHBSP6usvdhG7agbYeI769PRwZ0Z9YrIhZhnnaGD9hPni1tIQ9wyw3Trbqz+i1fbYJVtQyWx96np5eR/3IaydwTg5pVEh7fKukvUWOFwBmrdsX9vlE48/YMhjRtINouTWuWeWlpQvf/D1PuG9pDZ29qqJ5xIxmHb+gc/kB8w5vLQ7o/u35xGhSwHtDhwTEIa2KfTc7w4mQu1CJuDZz/1QHhNP6ZnvNqWiAdZlZUVJ3o+YWgCqMX1Y/sERf9vxSW3RkTCVm2xXppcwTKoCi4Y+9B9/5Hk5zanN1GMVu5dYFCjFv36s430JEttpkWEA1Oqe4AfZfvMsnTjLqG
\ No newline at end of file
diff --git a/spec/fixtures/files/users/admin/team1_password.crypt b/spec/fixtures/files/users/admin/team1_password.crypt
index bac01d7dc..8a8406031 100644
Binary files a/spec/fixtures/files/users/admin/team1_password.crypt and b/spec/fixtures/files/users/admin/team1_password.crypt differ
diff --git a/spec/fixtures/files/users/alice/team1_password.crypt b/spec/fixtures/files/users/alice/team1_password.crypt
index a7b8fae35..e871df083 100644
Binary files a/spec/fixtures/files/users/alice/team1_password.crypt and b/spec/fixtures/files/users/alice/team1_password.crypt differ
diff --git a/spec/fixtures/files/users/bob/team1_password.crypt b/spec/fixtures/files/users/bob/team1_password.crypt
index 6072c8850..c8d5000d2 100644
Binary files a/spec/fixtures/files/users/bob/team1_password.crypt and b/spec/fixtures/files/users/bob/team1_password.crypt differ
diff --git a/spec/fixtures/files/users/bob/team2_password.crypt b/spec/fixtures/files/users/bob/team2_password.crypt
index a918d7026..2821bd0bf 100644
Binary files a/spec/fixtures/files/users/bob/team2_password.crypt and b/spec/fixtures/files/users/bob/team2_password.crypt differ
diff --git a/spec/fixtures/files/users/root/team1_password.crypt b/spec/fixtures/files/users/root/team1_password.crypt
index 1cf86191b..7448ce1d5 100644
Binary files a/spec/fixtures/files/users/root/team1_password.crypt and b/spec/fixtures/files/users/root/team1_password.crypt differ
diff --git a/spec/fixtures/teammembers.yml b/spec/fixtures/teammembers.yml
index 642fa0b14..7d4677391 100644
--- a/spec/fixtures/teammembers.yml
+++ b/spec/fixtures/teammembers.yml
@@ -18,44 +18,44 @@
team1_bob:
team: team1
user: bob
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('bob', 'team1')}\"" %>
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('bob', 'team1')}\"" %>
team1_root:
team: team1
user: root
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('root', 'team1')}\"" %>
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('root', 'team1')}\"" %>
team1_alice:
team: team1
user: alice
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('alice', 'team1')}\"" %>
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('alice', 'team1')}\"" %>
team1_admin:
- team: team1
- user: admin
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('admin', 'team1')}\"" %>
+ team: team1
+ user: admin
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('admin', 'team1')}\"" %>
team2_bob:
- team: team2
- user: bob
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('bob', 'team2')}\"" %>
+ team: team2
+ user: bob
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('bob', 'team2')}\"" %>
bob_personal_team:
team: personal_team_bob
user: bob
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('bob', 'personal_team')}\"" %>
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('bob', 'personal_team')}\"" %>
alice_personal_team:
team: personal_team_alice
user: alice
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('alice', 'personal_team')}\"" %>
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('alice', 'personal_team')}\"" %>
admin_personal_team:
team: personal_team_admin
user: admin
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('admin', 'personal_team')}\"" %>
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('admin', 'personal_team')}\"" %>
root_personal_team:
team: personal_team_root
user: root
- password: <%= "!!binary \"#{FixturesHelper.read_team_password('root', 'personal_team')}\"" %>
+ encrypted_team_password: <%= "!!binary \"#{FixturesHelper.read_team_password('root', 'personal_team')}\"" %>
diff --git a/spec/fixtures/teams.yml b/spec/fixtures/teams.yml
index 8b346be3a..1896e52bf 100644
--- a/spec/fixtures/teams.yml
+++ b/spec/fixtures/teams.yml
@@ -22,6 +22,7 @@ team1:
description: public
visible: true
private: false
+ encryption_algorithm: 'AES256IV'
team2:
type: Team::Shared
@@ -29,33 +30,39 @@ team2:
description: public
visible: true
private: true
+ encryption_algorithm: 'AES256IV'
personal_team_bob:
type: Team::Personal
name: personal-team
private: true
personal_owner: bob
+ encryption_algorithm: 'AES256IV'
personal_team_alice:
type: Team::Personal
name: personal-team
private: true
personal_owner: alice
+ encryption_algorithm: 'AES256IV'
personal_team_root:
type: Team::Personal
name: personal-team
private: true
personal_owner: root
+ encryption_algorithm: 'AES256IV'
personal_team_admin:
type: Team::Personal
name: personal-team
private: true
personal_owner: admin
+ encryption_algorithm: 'AES256IV'
personal_team_conf_admin:
type: Team::Personal
name: personal-team
private: true
personal_owner: conf_admin
+ encryption_algorithm: 'AES256IV'
diff --git a/spec/migrations/move_file_entries_to_encryptable_files_spec.rb.disabled b/spec/migrations/move_file_entries_to_encryptable_files_spec.rb.disabled
index d78cac9de..97d96fd77 100644
--- a/spec/migrations/move_file_entries_to_encryptable_files_spec.rb.disabled
+++ b/spec/migrations/move_file_entries_to_encryptable_files_spec.rb.disabled
@@ -143,13 +143,14 @@ describe MoveFileEntriesToEncryptableFiles do
def encrypt(team_password)
return if cleartext_file.blank?
- self.file = ::Crypto::Symmetric::Aes256.encrypt(cleartext_file, team_password)
+ self.file = ::Crypto::Symmetric::Aes256.encrypt(cleartext_file, team_password)[:data]
end
def decrypt(team_password)
return if file.blank?
- self.cleartext_file = ::Crypto::Symmetric::Aes256.decrypt(file, team_password)
+ encrypted_values = { data: file, iv: nil }
+ self.cleartext_file = ::Crypto::Symmetric::Aes256.decrypt(encrypted_values, team_password)
end
end
# rubocop:enable Lint/ConstantDefinitionInBlock
diff --git a/spec/migrations/use_encrypted_data_for_account_credentials_spec.rb.disabled b/spec/migrations/use_encrypted_data_for_account_credentials_spec.rb.disabled
index 6aa79e21c..9e890eab7 100644
--- a/spec/migrations/use_encrypted_data_for_account_credentials_spec.rb.disabled
+++ b/spec/migrations/use_encrypted_data_for_account_credentials_spec.rb.disabled
@@ -172,7 +172,8 @@ class LegacyAccountCredentialsBefore < ApplicationRecord
crypted_value = send(attr)
return if crypted_value.blank?
- Crypto::Symmetric::Aes256.decrypt(crypted_value, team_password)
+ encrypted_values = { data: crypted_value, iv: nil }
+ Crypto::Symmetric::Aes256.decrypt(encrypted_values, team_password)
end
end
@@ -193,10 +194,12 @@ class LegacyAccountCredentialsAfter < ApplicationRecord
private
def decrypt_attr(attr, team_password)
- encrypted_value = encrypted_data[attr].try(:[], :data)
+ data = encrypted_data[attr].try(:[], :data)
+ iv = encrypted_data[attr].try(:[], :iv)
- cleartext_value = if encrypted_value
- Crypto::Symmetric::Aes256.decrypt(encrypted_value, team_password)
+ encrypted_values = { data: data, iv: iv }
+ cleartext_value = if data.present?
+ Crypto::Symmetric::Aes256.decrypt(encrypted_values, team_password)
end
instance_variable_set("@cleartext_#{attr}", cleartext_value)
diff --git a/spec/models/encryptable_spec.rb b/spec/models/encryptable_spec.rb
index 67fa7c0c7..ddbe80784 100644
--- a/spec/models/encryptable_spec.rb
+++ b/spec/models/encryptable_spec.rb
@@ -8,6 +8,7 @@
let(:bobs_private_key) { bob.decrypt_private_key('password') }
let(:encryptable) { encryptables(:credentials1) }
let(:team) { teams(:team1) }
+ let(:team_password) { team.decrypt_team_password(bob, bobs_private_key) }
it 'does not create second credential in same folder' do
params = {}
@@ -39,8 +40,6 @@
end
it 'decrypts all attributes' do
- team_password = team.decrypt_team_password(bob, bobs_private_key)
-
encryptable.decrypt(team_password)
expect(encryptable.cleartext_username).to eq('test')
@@ -53,8 +52,6 @@
end
it 'updates all attributes' do
- team_password = team.decrypt_team_password(bob, bobs_private_key)
-
encryptable.cleartext_username = 'new'
encryptable.cleartext_password = 'foo'
encryptable.cleartext_token = 'boo'
@@ -77,6 +74,17 @@
expect(encryptable.cleartext_custom_attr).to eq('yoo')
end
+ it 'removes attribute by saving nil value to database' do
+ encryptable.cleartext_username = nil
+ encryptable.encrypt(team_password)
+ encryptable.save!
+
+ encryptable.reload
+ encryptable.decrypt(team_password)
+
+ expect(encryptable.cleartext_username).to eq(nil)
+ end
+
it 'does not create credential if name is empty' do
params = {}
params[:name] = ''
diff --git a/spec/models/user/human_spec.rb b/spec/models/user/human_spec.rb
index 7e9624132..f48da50b4 100644
--- a/spec/models/user/human_spec.rb
+++ b/spec/models/user/human_spec.rb
@@ -95,7 +95,7 @@
context 'encryptables' do
it 'only returns encryptables where alice is member' do
encryptables = alice.encryptables
- expect(encryptables.count).to eq(2)
+ expect(encryptables.count).to eq(1)
expect(encryptables.first.name).to eq('Personal Mailbox')
end
end
diff --git a/spec/support/test_helper.rb b/spec/support/test_helper.rb
index 3a9db9d05..b13436e80 100644
--- a/spec/support/test_helper.rb
+++ b/spec/support/test_helper.rb
@@ -58,9 +58,9 @@ def oidc_settings
# static team passwords extracted from fixtures
def team1_password
- Base64.strict_decode64('LPTDTUOnL201Fn24GYP8ZRpE79m9ucBY8cF/tcCKcCs=')
+ Base64.strict_decode64('lxJqm1TGdue4y9b/njzh+vKtDXESeywOpu+kPp7qTJ8=')
end
def team2_password
- Base64.strict_decode64('Xyj5d0yF9D/XOCIi9Iz5bsgNs9KvvcKkJAtCsoENNj4=')
+ Base64.strict_decode64('A/UIOlRXNYTZDWsRBZmHwuTiujU/2HRi5rIQ8QNvWMA=')
end
diff --git a/spec/unit/serializers/folder_serializer_spec.rb b/spec/unit/serializers/folder_serializer_spec.rb
index 9be8a4bf4..39e675a07 100644
--- a/spec/unit/serializers/folder_serializer_spec.rb
+++ b/spec/unit/serializers/folder_serializer_spec.rb
@@ -7,23 +7,21 @@
let(:bob) { users(:bob) }
- context 'No files transferred' do
+ context 'Transferred count' do
- it 'should return 0 unread transferred files' do
+ it 'returns 0 if no transferred files in inbox folder' do
as_json = JSON.parse(FolderSerializer.new(folders(:inbox_folder_alice)).to_json)
expect(as_json['unread_transferred_count']).to eq(0)
end
- end
-
- context 'Some files transferred' do
- it 'should return 1 unread transferred file' do
+ it 'returns 1 if unread transferred file present in inbox folder' do
encryptable_file = Encryptable::File.new(name: 'file',
+ folder_id: alice.inbox_folder.id,
cleartext_file: file_fixture('test_file.txt').read,
content_type: 'text/plain')
- transfer_password = Crypto::Symmetric::Aes256.random_key
+ transfer_password = Crypto::Symmetric::Aes256iv.random_key
encryptable_file.encrypt(transfer_password)
@@ -40,5 +38,11 @@
expect(as_json['unread_transferred_count']).to eq(1)
end
+
+ it 'does not return count for non inbox folder' do
+ as_json = JSON.parse(FolderSerializer.new(folders(:folder2)).to_json)
+
+ expect(as_json['unread_transferred_count']).to eq(nil)
+ end
end
end
diff --git a/spec/unit/serializers/team_list_serializer_spec.rb b/spec/unit/serializers/team_list_serializer_spec.rb
index 05c618944..c4d4255dc 100644
--- a/spec/unit/serializers/team_list_serializer_spec.rb
+++ b/spec/unit/serializers/team_list_serializer_spec.rb
@@ -7,29 +7,21 @@
let(:bob) { users(:bob) }
- context 'No files transferred' do
+ context 'Transferred count' do
- it 'should return 0 unread transferred files' do
+ it 'returns 0 if no transferred files in inbox folder' do
as_json = JSON.parse(TeamListSerializer.new(teams(:personal_team_alice)).to_json)
expect(as_json['unread_count']).to eq(0)
end
- it 'should return nil unread transferred files when no personal team' do
- as_json = JSON.parse(TeamListSerializer.new(teams(:team2)).to_json)
-
- expect(as_json['unread_count']).to eq(nil)
- end
- end
-
- context 'Some files transferred' do
-
- it 'should return 1 unread transferred file' do
+ it 'returns 1 if unread transferred file present in inbox folder' do
encryptable_file = Encryptable::File.new(name: 'file',
+ folder_id: alice.inbox_folder.id,
cleartext_file: file_fixture('test_file.txt').read,
content_type: 'text/plain')
- transfer_password = Crypto::Symmetric::Aes256.random_key
+ transfer_password = Crypto::Symmetric::Aes256iv.random_key
encryptable_file.encrypt(transfer_password)
@@ -46,5 +38,11 @@
expect(as_json['unread_count']).to eq(1)
end
+
+ it 'does not return count for non personal team' do
+ as_json = JSON.parse(TeamListSerializer.new(teams(:team2)).to_json)
+
+ expect(as_json['unread_count']).to eq(nil)
+ end
end
end
diff --git a/spec/unit/utils/crypto/rsa_spec.rb b/spec/unit/utils/crypto/rsa_spec.rb
index bd032cb34..9d0c4a891 100644
--- a/spec/unit/utils/crypto/rsa_spec.rb
+++ b/spec/unit/utils/crypto/rsa_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_relative '../../../../app/utils/crypto/rsa'
-require_relative '../../../../app/utils/crypto/symmetric/aes256'
+require_relative '../../../../app/utils/crypto/symmetric'
describe Crypto::Rsa do
let(:keypair) { Crypto::Rsa.generate_new_keypair }
diff --git a/spec/unit/utils/crypto/symmetric/aes256_spec.rb b/spec/unit/utils/crypto/symmetric/aes256_spec.rb
index 939898f08..58e26f1ad 100644
--- a/spec/unit/utils/crypto/symmetric/aes256_spec.rb
+++ b/spec/unit/utils/crypto/symmetric/aes256_spec.rb
@@ -2,6 +2,7 @@
require 'spec_helper'
+require_relative '../../../../../app/utils/crypto/symmetric'
require_relative '../../../../../app/utils/crypto/symmetric/aes256'
require_relative '../../../../../app/utils/crypto/rsa'
diff --git a/spec/unit/utils/crypto/symmetric/aes256iv_spec.rb b/spec/unit/utils/crypto/symmetric/aes256iv_spec.rb
index f0149782d..00fb2b446 100644
--- a/spec/unit/utils/crypto/symmetric/aes256iv_spec.rb
+++ b/spec/unit/utils/crypto/symmetric/aes256iv_spec.rb
@@ -2,6 +2,8 @@
require 'spec_helper'
+require_relative '../../../../../app/utils/crypto/symmetric'
+require_relative '../../../../../app/utils/crypto/symmetric/aes256'
require_relative '../../../../../app/utils/crypto/symmetric/aes256iv'
describe Crypto::Symmetric::Aes256iv do
@@ -14,9 +16,8 @@
key = team_password
data = Base64.strict_decode64('test')
encrypted_values = described_class.encrypt(data, key)
- encrypted_data, iv = encrypted_values
- result = described_class.decrypt(encrypted_data, key, iv)
+ result = described_class.decrypt(encrypted_values, key)
encoded_result = Base64.strict_encode64(result)
expect(encoded_result).to eq('test')
end
diff --git a/spec/unit/utils/crypto/symmetric/recrypt_spec.rb b/spec/unit/utils/crypto/symmetric/recrypt_spec.rb
new file mode 100644
index 000000000..189a0a74a
--- /dev/null
+++ b/spec/unit/utils/crypto/symmetric/recrypt_spec.rb
@@ -0,0 +1,239 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Crypto::Symmetric::Recrypt do
+ let(:admin) { users(:admin) }
+ let(:bob) { users(:admin) }
+ let(:admin_pk) { admin.decrypt_private_key('password') }
+ let(:bob_pk) { bob.decrypt_private_key('password') }
+ let(:fabricate_team) { Fabricate(:non_private_team) }
+ let(:old_algo_team) { Fabricate(:old_encryption_algo_team) }
+
+ it 'does recrypt team encryptable if only token is set as attribute' do
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256')
+
+ expect(old_algo_team).to be_persisted
+ expect(old_algo_team.read_attribute(:encryption_algorithm)).to eq 'AES256'
+ expect(old_algo_team.encryption_algorithm).to eq 'AES256'
+ expect(old_algo_team.recrypt_state).to eq 'done'
+
+ team_password = old_algo_team.decrypt_team_password(admin, admin_pk)
+ encryptable = old_algo_team.encryptables.first
+ encryptable.decrypt(team_password)
+ encryptable_token = encryptable.cleartext_token
+ expect(encryptable_token).to be_present
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256IV')
+
+ described_class.new(admin, old_algo_team, admin_pk).perform
+
+ old_algo_team.reload
+ expect(old_algo_team.read_attribute(:encryption_algorithm)).to eq 'AES256IV'
+ expect(old_algo_team.encryption_algorithm).to eq 'AES256IV'
+ expect(old_algo_team.recrypt_state).to eq 'done'
+
+ encryptable = Encryptable.find(encryptable.id)
+ new_team_password = old_algo_team.decrypt_team_password(admin, admin_pk)
+ expect(new_team_password).not_to eq(team_password)
+ encryptable.decrypt(new_team_password)
+ expect(encryptable.cleartext_token).to eq(encryptable_token)
+
+ encrypted_data = encryptable.encrypted_data
+ expect(encrypted_data[:token][:iv]).to be_present
+ end
+
+ it 'does recrypt team encryptable if all attributes are set' do
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256')
+
+ expect(fabricate_team).to be_persisted
+ expect(fabricate_team.read_attribute(:encryption_algorithm)).to eq 'AES256'
+ expect(fabricate_team.encryption_algorithm).to eq 'AES256'
+ expect(fabricate_team.recrypt_state).to eq 'done'
+
+ team_password = fabricate_team.decrypt_team_password(admin, admin_pk)
+ encryptable = fabricate_team.encryptables.first
+ encryptable.decrypt(team_password)
+ encryptable_username = encryptable.cleartext_username
+ encryptable_password = encryptable.cleartext_password
+ encryptable_token = encryptable.cleartext_token
+ encryptable_pin = encryptable.cleartext_pin
+ encryptable_email = encryptable.cleartext_email
+ encryptable_custom_label = encryptable.cleartext_custom_attr_label
+ encryptable_custom_attr = encryptable.cleartext_custom_attr
+ expect(encryptable_username).to be_present
+ expect(encryptable_password).to be_present
+ expect(encryptable_token).to be_present
+ expect(encryptable_pin).to be_present
+ expect(encryptable_email).to be_present
+ expect(encryptable_custom_label).to be_present
+ expect(encryptable_custom_attr).to be_present
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256IV')
+
+ described_class.new(admin, fabricate_team, admin_pk).perform
+
+ fabricate_team.reload
+ expect(fabricate_team.read_attribute(:encryption_algorithm)).to eq 'AES256IV'
+ expect(fabricate_team.encryption_algorithm).to eq 'AES256IV'
+ expect(fabricate_team.recrypt_state).to eq 'done'
+
+ encryptable = Encryptable.find(encryptable.id)
+ new_team_password = fabricate_team.decrypt_team_password(admin, admin_pk)
+ expect(new_team_password).not_to eq(team_password)
+ encryptable.decrypt(new_team_password)
+
+ expect(encryptable.cleartext_username).to eq(encryptable_username)
+ expect(encryptable.cleartext_password).to eq(encryptable_password)
+ expect(encryptable.cleartext_token).to eq(encryptable_token)
+ expect(encryptable.cleartext_pin).to eq(encryptable_pin)
+ expect(encryptable.cleartext_email).to eq(encryptable_email)
+ expect(encryptable.cleartext_custom_attr_label).to eq(encryptable_custom_label)
+ expect(encryptable.cleartext_custom_attr).to eq(encryptable_custom_attr)
+
+ encrypted_data = encryptable.encrypted_data
+ expect(encrypted_data[:username][:iv]).to be_present
+ expect(encrypted_data[:password][:iv]).to be_present
+ expect(encrypted_data[:token][:iv]).to be_present
+ expect(encrypted_data[:pin][:iv]).to be_present
+ expect(encrypted_data[:email][:iv]).to be_present
+ expect(encrypted_data[:custom_attr][:iv]).to be_present
+ end
+
+ it 'does recrypt team encryptable if no attribute is set' do
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256')
+
+ expect(old_algo_team).to be_persisted
+ expect(old_algo_team.read_attribute(:encryption_algorithm)).to eq 'AES256'
+ expect(old_algo_team.encryption_algorithm).to eq 'AES256'
+ expect(old_algo_team.recrypt_state).to eq 'done'
+
+ team_password = old_algo_team.decrypt_team_password(admin, admin_pk)
+ encryptable = old_algo_team.encryptables.last
+ encryptable.decrypt(team_password)
+ encryptable_token = encryptable.cleartext_token
+ expect(encryptable_token).to be_nil
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256IV')
+
+ described_class.new(admin, old_algo_team, admin_pk).perform
+
+ old_algo_team.reload
+ expect(old_algo_team.read_attribute(:encryption_algorithm)).to eq 'AES256IV'
+ expect(old_algo_team.encryption_algorithm).to eq 'AES256IV'
+ expect(old_algo_team.recrypt_state).to eq 'done'
+
+ encryptable = Encryptable.find(encryptable.id)
+ new_team_password = old_algo_team.decrypt_team_password(admin, admin_pk)
+ expect(new_team_password).not_to eq(team_password)
+ encryptable.decrypt(new_team_password)
+ expect(encryptable.cleartext_token).to eq(encryptable_token)
+
+ encrypted_data = encryptable.encrypted_data
+ expect(encrypted_data[:username]).to be_nil
+ expect(encrypted_data[:password]).to be_nil
+ expect(encrypted_data[:pin]).to be_nil
+ expect(encrypted_data[:token]).to be_nil
+ expect(encrypted_data[:email]).to be_nil
+ end
+
+ it 'does not recrypt team encryptables if default algorithm is already in use' do
+ expect(fabricate_team).to be_persisted
+ # make sure encryption algorithm is persisted
+ expect(fabricate_team.read_attribute(:encryption_algorithm)).to eq 'AES256IV'
+ expect(fabricate_team.encryption_algorithm).to eq 'AES256IV'
+ expect(fabricate_team.recrypt_state).to eq 'done'
+
+ team_password = fabricate_team.decrypt_team_password(admin, admin_pk)
+ encryptable = fabricate_team.encryptables.where.not(name: 'broken encryptable').first
+ encryptable.decrypt(team_password)
+
+ username = encryptable.cleartext_username
+ password = encryptable.cleartext_password
+
+ described_class.new(admin, fabricate_team, admin_pk).perform
+
+ expect(fabricate_team.encryption_algorithm).to eq 'AES256IV'
+ expect(fabricate_team.recrypt_state).to eq 'done'
+
+ encryptable.reload.decrypt(team_password)
+
+ expect(encryptable.cleartext_username).to eq(username)
+ expect(encryptable.cleartext_password).to eq(password)
+ end
+
+ it 'aborts recrypt if error occurs' do
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256')
+
+ create_broken_encryptable(fabricate_team)
+
+ team_password = fabricate_team.decrypt_team_password(admin, admin_pk)
+ encryptable = fabricate_team.encryptables.where.not(name: 'broken encryptable').first
+
+ encryptable.decrypt(team_password)
+ username = encryptable.cleartext_username
+ password = encryptable.cleartext_password
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256IV')
+
+ expect do
+ described_class.new(admin, fabricate_team, admin_pk).perform
+ end.to raise_error(RuntimeError, 'Recrypt failed: wrong final block length')
+
+ expect(fabricate_team.reload.encryption_algorithm).to eq 'AES256'
+ expect(fabricate_team.recrypt_state).to eq 'failed'
+
+ encryptable.reload.decrypt(team_password)
+
+ expect(encryptable.cleartext_username).to eq(username)
+ expect(encryptable.cleartext_password).to eq(password)
+ end
+
+ it 'resets teampassword with a newly generated for each teammember' do
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256')
+
+ old_team_passwords = fabricate_team.teammembers.pluck(:encrypted_team_password)
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256IV')
+
+ described_class.new(admin, fabricate_team, admin_pk).perform
+
+ new_team_passwords = fabricate_team.teammembers.pluck(:encrypted_team_password)
+
+ expect(new_team_passwords).not_to eq(old_team_passwords)
+ end
+
+ it 'recrypts nested encryptable files' do
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256')
+
+ team_password = fabricate_team.decrypt_team_password(admin, admin_pk)
+ encryptable = fabricate_team.encryptables.first
+ file = Fabricate(:file, encryptable_credential: encryptable, team_password: team_password)
+
+ team_password = fabricate_team.decrypt_team_password(admin, admin_pk)
+ file.decrypt(team_password)
+ cleartext_file = file.cleartext_file
+ expect(cleartext_file).to be_present
+
+ stub_const('::Crypto::Symmetric::LATEST_ALGORITHM', 'AES256IV')
+
+ described_class.new(admin, fabricate_team, admin_pk).perform
+
+ file = Encryptable::File.find(file.id)
+ file.decrypt(fabricate_team.decrypt_team_password(admin, admin_pk))
+
+ expect(file.cleartext_file).to eq(cleartext_file)
+ end
+
+ private
+
+ def create_broken_encryptable(team)
+ broken_encryptable = Encryptable::Credentials.new
+ broken_encryptable.folder = team.folders.first
+ broken_encryptable.name = 'broken encryptable'
+ broken_encryptable.encrypted_data.[]=(:username, **{ iv: nil, data: 'broken' })
+ broken_encryptable.encrypted_data.[]=(:password, **{ iv: nil, data: 'broken' })
+ broken_encryptable.save!
+ end
+
+end
diff --git a/spec/unit/utils/encryptable_move_handler_spec.rb b/spec/unit/utils/encryptable_move_handler_spec.rb
index ef13f4cdc..34f6d9c21 100644
--- a/spec/unit/utils/encryptable_move_handler_spec.rb
+++ b/spec/unit/utils/encryptable_move_handler_spec.rb
@@ -15,7 +15,7 @@
private_key = decrypt_private_key(bob)
target_folder = folders(:folder2)
team_password = target_folder.team.decrypt_team_password(bob, private_key)
- Fabricate(:credential,
+ Fabricate(:credential_all_attrs,
folder: target_folder,
team_password: team_password,
name: 'credentials1')
@@ -109,8 +109,8 @@
credential.save!
- decrypted = credential.decrypt(new_folder.team.decrypt_team_password(bob, private_key))
- expect(decrypted).to eq('abc42-code-42')
+ credential.decrypt(new_folder.team.decrypt_team_password(bob, private_key))
+ expect(credential.cleartext_custom_attr).to eq('abc42-code-42')
expect(credential.folder).to eq(new_folder)
end
end