This is a Ruby tree! It shows every object from the Ruby Programming Language in a tree format.

OpenSSL::Cipher

        # OpenSSL::Cipher < Object

(from ruby core)
---

Provides symmetric algorithms for encryption and decryption. The
algorithms that are available depend on the particular version of
OpenSSL that is installed.

### Listing all supported algorithms

A list of supported algorithms can be obtained by

    puts OpenSSL::Cipher.ciphers

### Instantiating a Cipher

There are several ways to create a Cipher instance. Generally, a Cipher
algorithm is categorized by its name, the key length in bits and the
cipher mode to be used. The most generic way to create a Cipher is the
following

    cipher = OpenSSL::Cipher.new('<name>-<key length>-<mode>')

That is, a string consisting of the hyphenated concatenation of the
individual components name, key length and mode. Either all uppercase or
all lowercase strings may be used, for example:

    cipher = OpenSSL::Cipher.new('aes-128-cbc')

### Choosing either encryption or decryption mode

Encryption and decryption are often very similar operations for
symmetric algorithms, this is reflected by not having to choose
different classes for either operation, both can be done using the same
class. Still, after obtaining a Cipher instance, we need to tell the
instance what it is that we intend to do with it, so we need to call
either

    cipher.encrypt

or

    cipher.decrypt

on the Cipher instance. This should be the first call after creating the
instance, otherwise configuration that has already been set could get
lost in the process.

### Choosing a key

Symmetric encryption requires a key that is the same for the encrypting
and for the decrypting party and after initial key establishment should
be kept as private information. There are a lot of ways to create
insecure keys, the most notable is to simply take a password as the key
without processing the password further. A simple and secure way to
create a key for a particular Cipher is

    cipher = OpenSSL::Cipher.new('aes-256-cfb')
    cipher.encrypt
    key = cipher.random_key # also sets the generated key on the Cipher

If you absolutely need to use passwords as encryption keys, you should
use Password-Based Key Derivation Function 2 (PBKDF2) by generating the
key with the help of the functionality provided by
OpenSSL::PKCS5.pbkdf2_hmac_sha1 or OpenSSL::PKCS5.pbkdf2_hmac.

Although there is Cipher#pkcs5_keyivgen, its use is deprecated and it
should only be used in legacy applications because it does not use the
newer PKCS#5 v2 algorithms.

### Choosing an IV

The cipher modes CBC, CFB, OFB and CTR all need an "initialization
vector", or short, IV. ECB mode is the only mode that does not require
an IV, but there is almost no legitimate use case for this mode because
of the fact that it does not sufficiently hide plaintext patterns.
Therefore

**You should never use ECB mode unless you are absolutely sure that you
absolutely need it**

Because of this, you will end up with a mode that explicitly requires an
IV in any case. Although the IV can be seen as public information, i.e.
it may be transmitted in public once generated, it should still stay
unpredictable to prevent certain kinds of attacks. Therefore, ideally

**Always create a secure random IV for every encryption of your Cipher**

A new, random IV should be created for every encryption of data. Think
of the IV as a nonce (number used once) - it's public but random and
unpredictable. A secure random IV can be created as follows

    cipher = ...
    cipher.encrypt
    key = cipher.random_key
    iv = cipher.random_iv # also sets the generated IV on the Cipher

Although the key is generally a random value, too, it is a bad choice as
an IV. There are elaborate ways how an attacker can take advantage of
such an IV. As a general rule of thumb, exposing the key directly or
indirectly should be avoided at all cost and exceptions only be made
with good reason.

### Calling Cipher#final

ECB (which should not be used) and CBC are both block-based modes. This
means that unlike for the other streaming-based modes, they operate on
fixed-size blocks of data, and therefore they require a "finalization"
step to produce or correctly decrypt the last block of data by
appropriately handling some form of padding. Therefore it is essential
to add the output of OpenSSL::Cipher#final to your encryption/decryption
buffer or you will end up with decryption errors or truncated data.

Although this is not really necessary for streaming-mode ciphers, it is
still recommended to apply the same pattern of adding the output of
Cipher#final there as well - it also enables you to switch between modes
more easily in the future.

### Encrypting and decrypting some data

    data = "Very, very confidential data"

    cipher = OpenSSL::Cipher.new('aes-128-cbc')
    cipher.encrypt
    key = cipher.random_key
    iv = cipher.random_iv

    encrypted = cipher.update(data) + cipher.final
    ...
    decipher = OpenSSL::Cipher.new('aes-128-cbc')
    decipher.decrypt
    decipher.key = key
    decipher.iv = iv

    plain = decipher.update(encrypted) + decipher.final

    puts data == plain #=> true

### Authenticated Encryption and Associated Data (AEAD)

If the OpenSSL version used supports it, an Authenticated Encryption
mode (such as GCM or CCM) should always be preferred over any
unauthenticated mode. Currently, OpenSSL supports AE only in combination
with Associated Data (AEAD) where additional associated data is included
in the encryption process to compute a tag at the end of the encryption.
This tag will also be used in the decryption process and by verifying
its validity, the authenticity of a given ciphertext is established.

This is superior to unauthenticated modes in that it allows to detect if
somebody effectively changed the ciphertext after it had been encrypted.
This prevents malicious modifications of the ciphertext that could
otherwise be exploited to modify ciphertexts in ways beneficial to
potential attackers.

An associated data is used where there is additional information, such
as headers or some metadata, that must be also authenticated but not
necessarily need to be encrypted. If no associated data is needed for
encryption and later decryption, the OpenSSL library still requires a
value to be set - "" may be used in case none is available.

An example using the GCM (Galois/Counter Mode). You have 16 bytes *key*,
12 bytes (96 bits) *nonce* and the associated data *auth_data*. Be sure
not to reuse the *key* and *nonce* pair. Reusing an nonce ruins the
security guarantees of GCM mode.

    cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
    cipher.key = key
    cipher.iv = nonce
    cipher.auth_data = auth_data

    encrypted = cipher.update(data) + cipher.final
    tag = cipher.auth_tag # produces 16 bytes tag by default

Now you are the receiver. You know the *key* and have received *nonce*,
*auth_data*, *encrypted* and *tag* through an untrusted network. Note
that GCM accepts an arbitrary length tag between 1 and 16 bytes. You may
additionally need to check that the received tag has the correct length,
or you allow attackers to forge a valid single byte tag for the tampered
ciphertext with a probability of 1/256.

    raise "tag is truncated!" unless tag.bytesize == 16
    decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt
    decipher.key = key
    decipher.iv = nonce
    decipher.auth_tag = tag
    decipher.auth_data = auth_data

    decrypted = decipher.update(encrypted) + decipher.final

    puts data == decrypted #=> true
---
# Class methods:

    ciphers
    new

# Instance methods:

    auth_data=
    auth_tag
    auth_tag=
    auth_tag_len=
    authenticated?
    block_size
    ccm_data_len=
    decrypt
    encrypt
    final
    initialize_copy
    iv=
    iv_len
    iv_len=
    key=
    key_len
    key_len=
    name
    padding=
    pkcs5_keyivgen
    random_iv
    random_key
    reset
    update


      

This is MURDOC! A Ruby documentation browser inspired by Smalltalk-80. It allows you to learn about Ruby by browsing through its class hierarchies, and see any of its methods.