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')

For each algorithm supported, there is a class defined under the Cipher class that goes by the name of the
cipher, e.g. to obtain an instance of AES, you could also use

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.

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

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. Note that for backwards compatibility reasons, setting an IV
is not explicitly mandated by the Cipher
API. If not set, OpenSSL itself defaults to an all-zeroes IV ("\0", not the
character). 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

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.

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 #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 #final there as well - it also
enables you to switch between modes more easily in the future.

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.

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):

Public Instance Methods

auth_data = string → stringclick to toggle source

Sets the cipher’s additional authenticated data. This field must be set
when using AEAD cipher modes such as GCM or CCM. If no associated data
shall be used, this method must still be called with a
value of “”. The contents of this field should be non-sensitive data which
will be added to the ciphertext to generate the authentication tag which
validates the contents of the ciphertext.

The AAD must be set prior to encryption or decryption. In encryption mode,
it must be set after calling #encrypt and setting #key= and #iv=. When decrypting, the
authenticated data must be set after key, iv and especially
after the authentication tag has been set. I.e. set it
only after calling #decrypt, #key=, #iv= and #auth_tag= first.

Gets the authentication tag generated by Authenticated Encryption Cipher modes (GCM for example). This tag may
be stored along with the ciphertext, then set on the decryption cipher to
authenticate the contents of the ciphertext against changes. If the
optional integer parameter tag_len is given, the returned tag
will be tag_len bytes long. If the parameter is omitted, the
maximum length of 16 bytes will be returned. For maximum security, the
default of 16 bytes should be chosen.

Sets the authentication tag to verify the contents of the ciphertext. The
tag must be set after calling #decrypt, #key= and #iv=, but before assigning the
associated authenticated data using #auth_data= and of course,
before decrypting any of the ciphertext. After all decryption is performed,
the tag is verified automatically in the call to #final.

Returns the remaining data held in the cipher object. Further calls to #update or #final will return garbage. This call
should always be made as the last call of an encryption or decryption
operation, after after having fed the entire plaintext or ciphertext to the
Cipher instance.

If an authenticated cipher was used, a CipherError is raised if the tag could
not be authenticated successfully. Only call this method after setting the
authentication tag and passing the entire contents of the ciphertext into
the cipher.

Sets the cipher IV. Please note that since you should never be using ECB
mode, an IV is always explicitly required and should be set prior to
encryption. The IV itself can be safely transmitted in public, but it
should be unpredictable to prevent certain kinds of attacks. You may use #random_iv to create a secure
random IV.

Sets the cipher key. To generate a key, you should either use a secure
random byte string or, if the key is to be derived from a password, you
should rely on PBKDF2 functionality provided by OpenSSL::PKCS5. To generate a secure random-based
key, #random_key may be used.

Enables or disables padding. By default encryption operations are padded
using standard block padding and the padding is checked and removed when
decrypting. If the pad parameter is zero then no padding is performed, the
total amount of data encrypted or decrypted must then be a multiple of the
block size or an error will occur.

WARNING: This method is only PKCS5 v1.5 compliant
when using RC2, RC4-40, or DES with MD5 or SHA1. Using anything else (like
AES) will generate the key/iv using an OpenSSL specific method. This method
is deprecated and should no longer be used. Use a PKCS5 v2 key generation method from OpenSSL::PKCS5 instead.

Encrypts data in a streaming fashion. Hand consecutive blocks of data to
the update method in order to encrypt it. Returns the
encrypted data chunk. When done, the output of #final should be additionally added
to the result.