1

Я создаю приложение, которое требует соответствия HIPAA, которое, чтобы прервать преследование, означает, что я не могу позволить определенным соединениям свободно просматривать в базе данных (пациенты и рекомендации для них).Rails 4 зашифровать внешний ключ

Эти таблицы подключены через таблицу patients_recommendations в моем приложении, которая хорошо работала, пока я не добавил шифрование через attr_encrypted. Чтобы сократить количество шифрования и дешифрования (и связанных с ними служебных данных), я хотел бы просто шифровать patient_id в таблице patients_recommendations. Однако при изменении типа данных в string и имя столбца encrypted_patient_id, приложение брейки со следующей ошибкой при попытке повторно заполнить мою базу данных:

не может написать неизвестный атрибут `patient_id»

Я предполагаю, что это связано с тем, что соединение ищет столбец напрямую, а не через модель (имеет смысл, использование модели, вероятно, медленнее). Есть ли способ, которым я могу заставить Rails пройти через модель (где attr_encrypted добавил необходимые вспомогательные методы)?

Update:

В попытке найти работу вокруг, я пытался добавить before_save к модели, как так:

before_save :encrypt_patient_id 

... 

private 

def encrypt_patient_id 
    self.encrypted_patient_id = PatientRecommendation.encrypt(:patient_id, self.patient_id) 
    self.patient_id = nil 
end 

Это не работает либо, однако , что приводит к той же ошибке unknown attribute. Любое решение могло бы работать для меня (хотя первое касалось основной проблемы), любые идеи, почему before_save не вызывается при создании через ассоциацию?

+0

Будет ли односторонний хэш работать для вас вместо двухстороннего шифрования? Вы можете использовать 'SHA512 (secret_key + patient_id)' как внешний ключ, и все относительно просто. Большие символы делают дорогие индексы, хотя – bbozo

+0

Двусторонние шифровки обычно не выдерживают криптографического контроля, если у них фиксированный IV, и на первый взгляд кажется, что только фиксированное шифрование IV подходит для использования в качестве внешнего ключа, хеши работают, хотя .. Можете ли вы связать части спецификации HIPAA, которые задают это для вас? – bbozo

+0

В соответствии с HIPAA вам необходимо обеспечить персональную информацию о здоровье (PHI) и личную идентификационную информацию (PII) в пути и в состоянии покоя. Поскольку мое приложение позволит повторное использование и редактирование Рекомендаций, шифрование всех данных в этих полях (так что вы не можете сказать все рекомендации, сделанные для человека), похоже, больше накладных расходов, чем просто шифрование/дешифрование идентификаторов соединительной таблицы , Идея заключается в том, что Rails расшифровывает ключ, а затем объединяет, поэтому индексирование на этом ключе не требуется. –

ответ

1

вы, вероятно, магазин данные PII и данные PHI в отдельных БД. Шифруйте данные PII (включая любые ассоциации с местоположением поставщика или поставщика), а затем удалите все данные PHI, чтобы упростить их. До тех пор, пока между ними нет прямых связей, было бы приемлемо, чтобы данные PHI не были зашифрованы, поскольку они были анонимизированы.

+0

Это, вероятно, лучшее решение на данный момент (хотя и не достигается первоначальная цель хранения приложения в одной базе данных). –

+0

не могли бы вы объяснить больше? почему вы не можете сделать то же самое с разными таблицами в одном и том же дБ? что вы имеете в виду? большое спасибо – dowi

0

План А

Не устанавливайте patient_id в nil в encrypt_patient_id, так как не существует и проблема может уйти.

Кроме того, завершение обратного вызова с помощью nil или false остановит цепочку обратного вызова, поместит explicite true в конце метода.

Plan B, пересмотреть ваши варианты

Есть несколько вариантов - от прозрачного шифрования на уровне базы данных (формально шифруют данные на диске), шифрованные файловые системы для хранения некоторых табличных пространств, плоского из шифрования данных в столбцах.

шифрованное объединения столбцов звучит как дорога к несчастью для целого ряда причин, начиная от освещения вопросов проблем с производительностью при присоединении необходимо, которые могут быть довольно серьезными,

беда, вы в настоящее время переживаете с семенами похоже на его первый удар, вызванный этим тем, что обещает быть плохой дорогой (в этом случае activerecord, похоже, запутался, как обрабатывать вашу ассоциацию, он пытается установить patient_id на инициализацию и разрывы).

Накладные расходы на шифрование ограниченных данных могут быть не такими высокими, как вы думаете, не уверены, как все пойдет на HIPAA, но для PCI вам не рекомендуется рекламировать защищенные данные на экране, поэтому шифрование несет только небольшие накладные расходы, потому что это происходит относительно редко (бизнес-необходимость и т. д.).

Кроме того, память, вероятно, считается «не в состоянии покоя, а не в пути», вы можете теоретически кэшировать некоторые из ясных значений в течение ограниченного периода времени и, таким образом, сохранять накладные расходы на дешифрование.

В принципе, шифрование данных могут быть не так плохо, и шифрование ключей в базе данных могут быть хуже, чем вы думаете

Я предлагаю поговорить непосредственно, я делаю PCI DSS вещь соответствия, и эта тема меня интересует.

Опция: 1-полосная хэши для первичных/внешних ключей

PatientRecommendation бы хэш patient_id - назовем его patient_hash и Patient был бы способен генерировать такой же patient_hash от его id - но я хотел бы предложить хранение patient_hash в обеих таблицах, для Patient было бы первичный ключ для соединения и для PatientRecommendation было бы внешний ключ для соединения,

, таким образом, можно определить рельсы отношения в них Термины и рельсы больше не следует путать о вашей схеме отношения

has_many :patient_recommendations, primary_key: :patient_hash, foreign_key: :patient_hash 

и результат криптографически более надежный и простой для базы данных для обработки

Если вы непреклонны не хранить patient_hash в Patient вы может использовать простой SQL заявление, чтобы сделать отношения - менее удобные, но работоспособным - что-то в строках этого pseudosql:

JOIN ON generate_hash(patient.id) = patient_recommendations.patient_hash

Oracle, например, имеет возможность создавать функциональные индексы (думаю, create index generate_hash(patient.id)), поэтому этот подход может быть довольно эффективным в зависимости от вашего выбора базы данных.

Однако, играя с ключами присоединиться будет осложнит вашу жизнь много, даже с учетом этих мер


Я расширяющих на этот пост позже с дополнительными опциями

+0

Удаление строки 'self.patient_id = nil' не изменяет результат, хотя и не добавляет оператора печати или регистратора, что побуждает меня поверить, что по какой-либо причине« before_save »вообще не вызывается. –

+0

@JonathanBender, еще одно примечание: 'self.patient_id = nil', вероятно, блокирует дальнейшие« before_save »перехватчики, поэтому помещает явное' true' в конец 'encrypt_patient_id'. Можете ли вы показать, как вызывается update/save/create? – bbozo

+0

Все еще нет, соответствующая строка (в семенах) находится в блоке, произвольно назначающем рекомендации пациентам: 'p.patient_recommendations.create! (Рекомендация_id: rand.rand (1..rec_count))' –

Смежные вопросы