347af9dc76110fba6d255452d4b69ba704315bc7
[feedcatcher.git] / vendor / rails / activesupport / lib / active_support / message_encryptor.rb
1 require 'openssl'
2
3 module ActiveSupport
4 # MessageEncryptor is a simple way to encrypt values which get stored somewhere
5 # you don't trust.
6 #
7 # The cipher text and initialization vector are base64 encoded and returned to you.
8 #
9 # This can be used in situations similar to the MessageVerifier, but where you don't
10 # want users to be able to determine the value of the payload.
11 class MessageEncryptor
12 class InvalidMessage < StandardError; end
13 OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError
14
15 def initialize(secret, cipher = 'aes-256-cbc')
16 @secret = secret
17 @cipher = cipher
18 end
19
20 def encrypt(value)
21 cipher = new_cipher
22 # Rely on OpenSSL for the initialization vector
23 iv = cipher.random_iv
24
25 cipher.encrypt
26 cipher.key = @secret
27 cipher.iv = iv
28
29 encrypted_data = cipher.update(Marshal.dump(value))
30 encrypted_data << cipher.final
31
32 [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--")
33 end
34
35 def decrypt(encrypted_message)
36 cipher = new_cipher
37 encrypted_data, iv = encrypted_message.split("--").map {|v| ActiveSupport::Base64.decode64(v)}
38
39 cipher.decrypt
40 cipher.key = @secret
41 cipher.iv = iv
42
43 decrypted_data = cipher.update(encrypted_data)
44 decrypted_data << cipher.final
45
46 Marshal.load(decrypted_data)
47 rescue OpenSSLCipherError, TypeError
48 raise InvalidMessage
49 end
50
51 def encrypt_and_sign(value)
52 verifier.generate(encrypt(value))
53 end
54
55 def decrypt_and_verify(value)
56 decrypt(verifier.verify(value))
57 end
58
59
60
61 private
62 def new_cipher
63 OpenSSL::Cipher::Cipher.new(@cipher)
64 end
65
66 def verifier
67 MessageVerifier.new(@secret)
68 end
69 end
70 end