class Gibberish::AES

# Handles AES encryption and decryption with some sensible defaults

- 256 bit AES encryption
- GCM mode with Authentication
- 100,000 iterations of PBKDF2_HMAC for key strengthening

## Compatibility with SJCL

It outputs into a format that is compatible with SJCL and easy to
consume in browsers/Node.js

## Basic Usage

### Encrypting

cipher = Gibberish::AES.new('p4ssw0rd')
cipher.encrypt("some secret text")
#=> Outputs a JSON string containing all the necessary information

### Decrypting

cipher = Gibberish::AES.new('p4ssw0rd')
cipher.decrypt('{"iv":"I4XKgNfMNkYhvzXc","v":1,"iter":1000,"ks":128,"ts":64,"mode":"gcm","adata":"123abc","cipher":"aes","salt":"PJsit8L16Ug=","ct":"5sEBsHXQqLXLOjxuVQK7fGZVdrMyRGDJ"}')
#=> "some secret text"

#### Including Authenticated data.

GCM mode allows you to include “Authenticated Data” with the ciphertext, if you wish. For an overview of Authenticated Data, see this post: [crypto.stackexchange.com/a/15701](http://crypto.stackexchange.com/a/15701)

Using AD is easy with Gibberish

cipher = Gibberish::AES.new('p4ssw0rd')
ciphertext = cipher.encrypt("Some secret data", "my authenticated data")
plaintext = cipher.decrypt(ciphertext)
#=> "some secret text"
plaintext.adata
# => "my authenticated data"

## Interoperability with SJCL's GCM mode AES

#### Decrypting

“`javascript // In the browser var cleartext = sjcl.decrypt('key', '[output from Gibberish AES]'); “`

#### Encrypting

Ruby OpenSSL cannot handle an IV longer than 12 bytes, therefore we need to tell SJCL to only use a 3 word IV value. See: github.com/bitwiseshiftleft/sjcl/issues/180

“`javascript // In the browser var ciphertext = sjcl.encrypt('key', 'plain text', {mode: 'gcm', iv: sjcl.random.randomWords(3, 0)}); “`

## Backward compatibility with older pre 2.0 Gibberish

Gibberish was previously designed to be compatible with OpenSSL on the command line with CBC mode AES.
This has been deprecated in favor of GCM mode. However, you may still
decrypt and encrypt using legacy convenience methods below:

(Note: OpenSSL "enc" uses a non-standard file format which lacks [key stretching](http://en.wikipedia.org/wiki/Key_stretching), this means less secure passwords are more susceptible to brute forcing.)

### AES-256-CBC mode

cipher = Gibberish::AES::CBC.new('p4ssw0rd')
cipher_text = cipher.encrypt("some secret text")
# => U2FsdGVkX1/D7z2azGmmQELbMNJV/n9T/9j2iBPy2AM=

cipher.decrypt(cipher_text)

# From the command line
echo "U2FsdGVkX1/D7z2azGmmQELbMNJV/n9T/9j2iBPy2AM=\n" | openssl enc -d -aes-256-cbc -a -k p4ssw0rd

Public Class Methods

new(password, opts={}) click to toggle source

Returns the AES object

@param [String] password @param [Hash] opts @option opts [Symbol] :mode ('gcm') the AES mode to use @option opts [Symbol] :ks (256) keystrength @option opts [Symbol] :iter (100_000) number of PBKDF2 iterations to run on the password @option opts [Symbol] :max_iter (100_000) maximum allow iterations, set to prevent DOS attack of someone setting a large 'iter' value in the ciphertext JSON @option opts [Symbol] :ts (64) length of the authentication data hash

# File lib/gibberish/aes.rb, line 91
def initialize(password, opts={})
  @cipher = SJCL.new(password, opts)
end

Public Instance Methods

decrypt(ciphertext) click to toggle source

Returns a Plaintext object (essentially a String with an additional 'adata' attribute)

@param [String] ciphertext

# File lib/gibberish/aes.rb, line 106
def decrypt(ciphertext)
  @cipher.decrypt(ciphertext)
end
encrypt(data, authenticated_data='') click to toggle source

Returns the ciphertext in the form of a JSON string

@param [String] data @param [String] authenticated_data (Won't be encrypted)

# File lib/gibberish/aes.rb, line 99
def encrypt(data, authenticated_data='')
  @cipher.encrypt(data, authenticated_data)
end