lib/fernet/encryption.rb
require 'openssl'
module Fernet
# Internal: Encapsulates encryption and signing primitives
module Encryption
AES_BLOCK_SIZE = 16.freeze
# Internal: Encrypts the provided message using a AES-128-CBC cipher with a
# random IV and the provided encryption key
#
# opts - a hash containing
# * message - the message to encrypt
# * key - the encryption key
# * iv - override for the random IV, only used for testing
#
# Examples
#
# ciphertext, iv = Fernet::Encryption.encrypt(
# message: 'this is a secret', key: encryption_key
# )
#
# Returns a two-element array containing the ciphertext and the random IV
def self.encrypt(opts)
cipher = OpenSSL::Cipher.new('AES-128-CBC')
cipher.encrypt
iv = opts[:iv] || cipher.random_iv
cipher.iv = iv
cipher.key = opts[:key]
ciphertext = ""
if opts[:message] && !opts[:message].empty?
ciphertext += cipher.update(opts[:message])
end
ciphertext += cipher.final
[ciphertext, iv]
end
# Internal: Decrypts the provided ciphertext using a AES-128-CBC cipher with a
# the provided IV and encryption key
#
# opts - a hash containing
# * ciphertext - encrypted message
# * key - encryption key used to encrypt the message
# * iv - initialization vector used in the ciphertext's cipher
#
# Examples
#
# ciphertext, iv = Fernet::Encryption.encrypt(
# message: 'this is a secret', key: encryption_key
# )
#
# Returns a two-element array containing the ciphertext and the random IV
def self.decrypt(opts)
decipher = OpenSSL::Cipher.new('AES-128-CBC')
decipher.decrypt
decipher.iv = opts[:iv]
decipher.key = opts[:key]
decipher.update(opts[:ciphertext]) + decipher.final
end
# Internal: Creates an HMAC signature (sha356 hashing) of the given bytes
# with the provided signing key
#
# key - the signing key
# bytes - blob of bytes to sign
#
# Returns the HMAC signature as a string
def self.hmac_digest(key, bytes)
OpenSSL::HMAC.digest('sha256', key, bytes)
end
end
end