diff options
author | Michael Koziarski <michael@koziarski.com> | 2008-11-25 20:27:54 +0100 |
---|---|---|
committer | Michael Koziarski <michael@koziarski.com> | 2008-11-25 20:51:30 +0100 |
commit | 07abc5efe1bc71902b0c517ef97dcb36564f2336 (patch) | |
tree | f7874f9b0a4d01e63245a637d79983f4cefbf058 /activesupport/lib/active_support | |
parent | e126e1aac07d353e10fe9871fc3fc3f040cc8911 (diff) | |
download | rails-07abc5efe1bc71902b0c517ef97dcb36564f2336.tar.gz rails-07abc5efe1bc71902b0c517ef97dcb36564f2336.tar.bz2 rails-07abc5efe1bc71902b0c517ef97dcb36564f2336.zip |
Add a MessageEncryptor, just like MessageVerifier but using symmetric key encryption.
The use of encryption prevents people from seeing any potentially secret values you've used. It also supports and encrypt_and_sign model to prevent people from tampering with the bits and creating random junk that gets fed to
A motivated coder could use this to add an :encrypt=>true option to the cookie store.
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r-- | activesupport/lib/active_support/message_encryptor.rb | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb new file mode 100644 index 0000000000..de2b4bee76 --- /dev/null +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -0,0 +1,69 @@ +require 'openssl' + +module ActiveSupport + # MessageEncryptor is a simple way to encrypt values which get stored somewhere + # you don't trust. + # + # The cipher text and initialization vector are base64 encoded and returned to you. + # + # This can be used in situations similar to the MessageVerifier, but where you don't + # want users to be able to determine the value of the payload. + class MessageEncryptor + class InvalidMessage < StandardError; end + + def initialize(secret, cipher = 'aes-256-cbc') + @secret = secret + @cipher = cipher + end + + def encrypt(value) + cipher = new_cipher + # Rely on OpenSSL for the initialization vector + iv = cipher.random_iv + + cipher.encrypt + cipher.key = @secret + cipher.iv = iv + + encrypted_data = cipher.update(Marshal.dump(value)) + encrypted_data << cipher.final + + [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") + end + + def decrypt(encrypted_message) + cipher = new_cipher + encrypted_data, iv = encrypted_message.split("--").map {|v| ActiveSupport::Base64.decode64(v)} + + cipher.decrypt + cipher.key = @secret + cipher.iv = iv + + decrypted_data = cipher.update(encrypted_data) + decrypted_data << cipher.final + + Marshal.load(decrypted_data) + rescue OpenSSL::CipherError, TypeError + raise InvalidMessage + end + + def encrypt_and_sign(value) + verifier.generate(encrypt(value)) + end + + def decrypt_and_verify(value) + decrypt(verifier.verify(value)) + end + + + + private + def new_cipher + OpenSSL::Cipher::Cipher.new(@cipher) + end + + def verifier + MessageVerifier.new(@secret) + end + end +end
\ No newline at end of file |