Pull to refresh

Шифрование и дешифрование аттрибутов в Ruby on Rails

Проблема с шифрование/дешифрование строки на Ruby для меня казалась до сегодняшнего дня очень простой задачей. Во всем изветсном любителям и профессионалам по укладке рельсов учебнике «Agile web development Ruby on Rails» описывается как зашифровать строку с помощью соли и функции Digest::SHA1.digest. Но как расшифровать эту строку нигде не описано. Мало того, потратив пол дня в поисках данного решения, я ничего подобного не нашел, кроме одной фразы на каком-то форуме: «это не возможно». Кто читал данную книгу, помнит, что после того как строка зашифрована, её только проверяют с ведённым паролем пользователем, впоследствии зашифрованным таким же способом. Но расшифровать её никто и не пытался. Правильно — ведь это невозможно!

Но что делать, если нужно дешифровать сохранённый пароль? Ситуация простая — моё приложение будет обращаться к API некоторого сервиса, для авторизации которого нужен пароль в незашифрованном виде. Потратив ещё несколько часов на поиски, я нашёл, что это можно сделать с помощью модуля Base64. Итого у меня получился такой вот модуль:

#lfield_encriptor.rb
module FieldEncryptor
module ClassMethods
def safe_fields(*args)
args.each do |a|
define_method(a) do
decrypt_field(a)
end
define_method("#{a}=") do |val|
self.write_attribute(a, val)
encrypt_field(a)
end
end
end
end

def self.included(base)
base.extend(ClassMethods)
end

private
def encrypt_field(field)
self.write_attribute(field, Base64.encode64(self.read_attribute(field)))
end

def decrypt_field(field)
Base64.decode64(self.read_attribute(field))
end
end

Ложим его в lib прокта. Далее его можно заюзать в любой модельке:
class User < ActiveRecord::Base
include FieldEncryptor
safe_fields :password
end

Протестируем, что ж у нас получилось:

andrey@andrey:~/projects/test$ script/console
>> u = User.first
=> #<User id: 1, password: «NHNwdXRuMWs=\n»>
>> u.password = 'test'
=> «test»
>> u.save
=> true
>> u
=> #<User id: 1, password: «dGVzdA==\n»>
>> u.password
=> «test»

Как видно из примера все работает как нужно. В базу сохраняется зашифрованная строка, но обращаясь к атрибуту мы имеем незашифрованную строку.

Данное решение имеет большой недостаток: если знать, что строка зашифрованна данным методом, то дешифровать её проще простого. Вследствие этого, такое решение не надежно и пароль хакеры взломают очень просто.

PS. Шифровать и дешифровать строку можно многими методами. Например, есть гемы encryptor, attr_encrypted и т. п. Но есть проблема с сохранением зашифрованной строки с помощью алгоритмов, используемыми этими плагинами, в базу (в частности mysql у меня не получилось). В такой строке постоянно появляется какой-то символ (чёрный ромб с вопросиком внутри), после которого все символы в базе просто обрезается и при выборке получается уже неполная строка. Как и из-за чего это происходит разобраться у меня не получилось. Так или иначе это тема не для рассуждений в этой статье. Надеюсь, моя статья была кому-то полезна. Спасибо за внимание.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.