module Garcon::Crypto

Crypto uses the AES-256-CBC algorithm by default to encrypt strings securely. It uses both an initialization vector (IV) and a salt to perform this encryption as securely as possible.

@example

Use `#encrypt` to encrypt a string.
  text = "what is 42?"
  salt = "9e5f851900cad8892ac8b737b7370cbe"
  pass = "!mWh0!s@y!m"
  encrypted_text = Crypto.encrypt(text, set_password, set_salt)
    # => "+opVpqJhQsD3dbOQ8GAGjmq7slIms2zCQmOrMxJGpqQ=\n"

Then to decrypt the string use `#decrypt`.
  Crypto.decrypt(encrypted_text, pass, salt)
    # => "what is 42?"

You can also set the salt and password on a configuration object.
  Garcon::Crypto.config do |config|
    config.password = "!mWh0!s@y!m"
    config.salt     = "9e5f851900cad8892ac8b737b7370cbe"
  end

Now you can #encrypt and #decrypt without specifying a salt and password.
  encrypted_text = Crypto.encrypt(text)
    # => "HQRabUG8BcS+yZR8yG9TqQWfFPFYXztRgoQjdAUseFU=\n"
  Crypto.decrypt(encrypted_text)
    # => "what is 42?"

What you probably want to use this for is directly on a String.
  encrypted_text = text.encrypt
    # => "ew2SEyf+09WdPJHRjmBGp4g6C1oSQaDbQiZ/7WEceEc=\n"
  encrypted_text.decrypt
    # => "what is 42?"

@note

The salt needs to be unique per-use per-encrypted string. Every time a
string is encrypted, it should be hashed using a new random salt. Never
reuse a salt. The salt also needs to be long, so that there are many
possible salts. As a rule of thumb, the salt should be at least 32 random
bytes. Garcon includes a easy helper for you to generate a random binary
string, `String.random_binary(SIZE)`, where size  is the size in bytes.

Constants

CIPHER_TYPE
CRYPTERATIONS
HASH_BYTE_SIZE
SALT_BYTE_SIZE

The default size, iterations and cipher encryption algorithm used.

Public Instance Methods

decrypt(encrypted_text, password = nil, salt = nil) click to toggle source

Decrypt the given string, using the salt and password supplied.

@param [String] encrypted_text

The text to decrypt, probably produced with #decrypt.

@param [String] password

Secret passphrase to decrypt with.

@param [String] salt

The cryptographically secure pseudo-random string used to spice up the
encryption of your strings.

@return [String]

The decrypted plain_text.

@api public

# File lib/garcon/utility/crypto.rb, line 180
def decrypt(encrypted_text, password = nil, salt = nil)
  password = password.nil? ? Garcon.crypto.password : password
  salt     = salt.nil?     ? Garcon.crypto.salt     : salt

  iv_ciphertext = Base64.decode64(encrypted_text)
  cipher        = new_cipher(:decrypt, password, salt)
  cipher.iv, ciphertext = separate_iv_ciphertext(cipher, iv_ciphertext)
  plain_text    = cipher.update(ciphertext)
  plain_text   << cipher.final
  plain_text
end
encrypt(plain_text, password = nil, salt = nil) click to toggle source

Encrypt the given string using the AES-256-CBC algorithm.

@param [String] plain_text

The text to encrypt.

@param [String] password

Secret passphrase to encrypt with.

@param [String] salt

A cryptographically secure pseudo-random string (SecureRandom.base64)
to add a little spice to your encryption.

@return [String]

Encrypted text, can be deciphered with #decrypt.

@api public

# File lib/garcon/utility/crypto.rb, line 153
def encrypt(plain_text, password = nil, salt = nil)
  password = password.nil? ? Garcon.crypto.password : password
  salt     = salt.nil?     ? Garcon.crypto.salt     : salt

  cipher      = new_cipher(:encrypt, password, salt)
  cipher.iv   = iv = cipher.random_iv
  ciphertext  = cipher.update(plain_text)
  ciphertext << cipher.final
  Base64.encode64(combine_iv_ciphertext(iv, ciphertext))
end
salted_hash(password) click to toggle source

Generates a special hash known as a SPASH, a PBKDF2-HMAC-SHA1 Salted Password Hash for safekeeping.

@param [String] password

A password to generating the SPASH, salted password hash.

@return [Hash]

`:salt` contains the unique salt used, `:pbkdf2` contains the password
hash. Save both the salt and the hash together.

@see Garcon::Crypto#validate_salt

@api public

# File lib/garcon/utility/crypto.rb, line 205
def salted_hash(password)
  salt   = SecureRandom.random_bytes(SALT_BYTE_SIZE)
  pbkdf2 = OpenSSL::PKCS5::pbkdf2_hmac_sha1(
             password, salt, CRYPTERATIONS, HASH_BYTE_SIZE
           )

  { salt: salt, pbkdf2: Base64.encode64(pbkdf2) }
end