This abstract class provides a common interface to message digest implementation classes written in C.
standard dynamic load exception
Used internally by Fiddle::Importer
A C struct wrapper
Fiddle::Pointer
is a class to handle C pointers
Provides symmetric algorithms for encryption and decryption. The algorithms that are available depend on the particular version of OpenSSL
that is installed.
A list of supported algorithms can be obtained by
puts OpenSSL::Cipher.ciphers
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')
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
# these are equivalent cipher = OpenSSL::Cipher::AES.new(128, :CBC) cipher = OpenSSL::Cipher::AES.new(128, 'CBC') cipher = OpenSSL::Cipher::AES.new('128-CBC')
Finally, due to its wide-spread use, there are also extra classes defined for the different key sizes of AES
cipher = OpenSSL::Cipher::AES128.new(:CBC) cipher = OpenSSL::Cipher::AES192.new(:CBC) cipher = OpenSSL::Cipher::AES256.new(:CBC)
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
cipher = OpenSSL::AES256.new(: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.
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
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.
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.
data = "Very, very confidential data" cipher = OpenSSL::Cipher::AES.new(128, :CBC) cipher.encrypt key = cipher.random_key iv = cipher.random_iv encrypted = cipher.update(data) + cipher.final ... decipher = OpenSSL::Cipher::AES.new(128, :CBC) decipher.decrypt decipher.key = key decipher.iv = iv plain = decipher.update(encrypted) + decipher.final puts data == plain #=> true
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.
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):
cipher = OpenSSL::Cipher::AES.new(128, :GCM) cipher.encrypt key = cipher.random_key iv = cipher.random_iv cipher.auth_data = "" encrypted = cipher.update(data) + cipher.final tag = cipher.auth_tag decipher = OpenSSL::Cipher::AES.new(128, :GCM) decipher.decrypt decipher.key = key decipher.iv = iv decipher.auth_tag = tag decipher.auth_data = "" plain = decipher.update(encrypted) + decipher.final puts data == plain #=> true
OpenSSL::Config
Configuration for the openssl library.
Many system’s installation of openssl library will depend on your system configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE
for the location of the file for your host.
If an object defines encode_with
, then an instance of Psych::Coder
will be passed to the method when the object is being serialized. The Coder
automatically assumes a Psych::Nodes::Mapping
is being emitted. Other objects like Sequence and Scalar may be emitted if seq=
or scalar=
are called, respectively.
Psych::Handler
is an abstract base class that defines the events used when dealing with Psych::Parser
. Clients who want to use Psych::Parser
should implement a class that inherits from Psych::Handler
and define events that they can handle.
Psych::Handler
defines all events that Psych::Parser
can possibly send to event handlers.
See Psych::Parser
for more details
This class works in conjunction with Psych::Parser
to build an in-memory parse tree that represents a YAML document.
parser = Psych::Parser.new Psych::TreeBuilder.new parser.parse('--- foo') tree = parser.handler.root
See Psych::Handler
for documentation on the event methods used in this class.
This class handles only scanner events, which are dispatched in the ‘right’ order (same with input).
Socket::AncillaryData
represents the ancillary data (control information) used by sendmsg and recvmsg system call. It contains socket family
, control message (cmsg) level
, cmsg type
and cmsg data
.
Syslog::Logger
is a Logger
work-alike that logs via syslog instead of to a file. You can use Syslog::Logger
to aggregate logs between multiple machines.
By default, Syslog::Logger
uses the program name ‘ruby’, but this can be changed via the first argument to Syslog::Logger.new
.
NOTE! You can only set the Syslog::Logger
program name when you initialize Syslog::Logger
for the first time. This is a limitation of the way Syslog::Logger
uses syslog (and in some ways, a limitation of the way syslog(3) works). Attempts to change Syslog::Logger
‘s program name after the first initialization will be ignored.
The following will log to syslogd on your local machine:
require 'syslog/logger' log = Syslog::Logger.new 'my_program' log.info 'this line will be logged via syslog(3)'
Also the facility may be set to specify the facility level which will be used:
log.info 'this line will be logged using Syslog default facility level' log_local1 = Syslog::Logger.new 'my_program', Syslog::LOG_LOCAL1 log_local1.info 'this line will be logged using local1 facility level'
You may need to perform some syslog.conf setup first. For a BSD machine add the following lines to /etc/syslog.conf:
!my_program *.* /var/log/my_program.log
Then touch /var/log/my_program.log and signal syslogd with a HUP (killall -HUP syslogd, on FreeBSD).
If you wish to have logs automatically roll over and archive, see the newsyslog.conf(5) and newsyslog(8) man pages.