Class: Rack::Session::EncryptedCookie::Encryptor
- Inherits:
-
Object
- Object
- Rack::Session::EncryptedCookie::Encryptor
- Defined in:
- lib/encrypted_cookie/encryptor.rb
Overview
Encrypts messages with authentication
The use of authentication is essential to avoid Chosen Ciphertext Attacks. By using this in an encrypt then MAC form, we avoid some attacks such as e.g. being used as a CBC padding oracle to decrypt the ciphertext.
Instance Method Summary collapse
-
#decrypt(ciphertext) ⇒ Object
decrypts base64 encoded ciphertext.
-
#encrypt(message) ⇒ Object
Encrypts message.
-
#initialize(secret, cipher = 'aes-256-cbc', hmac = 'SHA256') ⇒ Encryptor
constructor
Create the encryptor.
Constructor Details
#initialize(secret, cipher = 'aes-256-cbc', hmac = 'SHA256') ⇒ Encryptor
Create the encryptor
Pass in the secret, which should be at least 32-bytes worth of entropy, e.g. a string generated by ‘SecureRandom.hex(32)`. This also allows specification of the algorithm for the cipher and MAC. But don’t change that unless you’re very sure.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/encrypted_cookie/encryptor.rb', line 19 def initialize(secret, cipher = 'aes-256-cbc', hmac = 'SHA256') @cipher = cipher @hmac = hmac # use the HMAC to derive two independent keys for the encryption and # authentication of ciphertexts It is bad practice to use the same key # for encryption and authentication. This also allows us to use all # of the entropy in a long key (e.g. 64 hex bytes) when straight # assignement would could result in assigning a key with a much # reduced key space. Also, the personalisation strings further help # reduce the possibility of key reuse by ensuring it should be unique # to this gem, even with shared secrets. @encryption_key = hmac("EncryptedCookie Encryption", secret) @authentication_key = hmac("EncryptedCookie Authentication", secret) end |
Instance Method Details
#decrypt(ciphertext) ⇒ Object
decrypts base64 encoded ciphertext
First, it checks the message tag and returns nil if that fails to verify. Otherwise, the data is passed on to the AES function for decryption.
51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/encrypted_cookie/encryptor.rb', line 51 def decrypt(ciphertext) ciphertext = ciphertext.unpack('m').first tag = ciphertext[0, hmac_length] ciphertext = ciphertext[hmac_length..-1] # make sure we actually had enough data for the tag too. if tag && ciphertext && (tag, ciphertext) decrypt_ciphertext(ciphertext) else nil end end |
#encrypt(message) ⇒ Object
Encrypts message
Returns the base64 encoded ciphertext plus IV. In addtion, the message is prepended with a MAC code to prevent chosen ciphertext attacks.
40 41 42 43 44 45 |
# File 'lib/encrypted_cookie/encryptor.rb', line 40 def encrypt() # encrypt the message encrypted = () [(encrypted) + encrypted].pack('m0') end |