Module: Garcon::Crypto

Extended by:
Crypto
Included in:
Crypto
Defined in:
lib/garcon/utility/crypto.rb

Overview

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.

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.

Examples:

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?"

Defined Under Namespace

Modules: String Classes: Configuration

Constant Summary collapse

SALT_BYTE_SIZE =

The default size, iterations and cipher encryption algorithm used.

64
HASH_BYTE_SIZE =
256
CRYPTERATIONS =
4096
CIPHER_TYPE =
'aes-256-cbc'

Instance Method Summary collapse

Instance Method Details

#decrypt(encrypted_text, password = nil, salt = nil) ⇒ String

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

Parameters:

  • encrypted_text (String)

    The text to decrypt, probably produced with #decrypt.

  • password (String) (defaults to: nil)

    Secret passphrase to decrypt with.

  • salt (String) (defaults to: nil)

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

Returns:

  • (String)

    The decrypted plain_text.



180
181
182
183
184
185
186
187
188
189
190
# 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) ⇒ String

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

Parameters:

  • plain_text (String)

    The text to encrypt.

  • password (String) (defaults to: nil)

    Secret passphrase to encrypt with.

  • salt (String) (defaults to: nil)

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

Returns:

  • (String)

    Encrypted text, can be deciphered with #decrypt.



153
154
155
156
157
158
159
160
161
162
# 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) ⇒ Hash

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

Parameters:

  • password (String)

    A password to generating the SPASH, salted password hash.

Returns:

  • (Hash)

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

See Also:

  • #validate_salt


205
206
207
208
209
210
211
212
# 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