Used internally by Fiddle::Importer
Wrapper for arrays within a struct
A pointer to a C structure
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')
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::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.
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.
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.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
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
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.
Generic Error for all of OpenSSL::BN
(big num)
Document-class: OpenSSL::HMAC
OpenSSL::HMAC
allows computing Hash-based Message Authentication Code (HMAC
). It is a type of message authentication code (MAC) involving a hash function in combination with a key. HMAC
can be used to verify the integrity of a message as well as the authenticity.
OpenSSL::HMAC
has a similar interface to OpenSSL::Digest
.
key = "key" data = "message-to-be-authenticated" mac = OpenSSL::HMAC.hexdigest("SHA256", key, data) #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
data1 = File.read("file1") data2 = File.read("file2") key = "key" digest = OpenSSL::Digest.new('SHA256') hmac = OpenSSL::HMAC.new(key, digest) hmac << data1 hmac << data2 mac = hmac.digest
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.
The superclass for all exceptions raised by Ruby/zlib.
The following exceptions are defined as subclasses of Zlib::Error
. These exceptions are raised when zlib library functions return with an error status.
Subclass of Zlib::Error
when zlib returns a Z_DATA_ERROR.
Usually if a stream was prematurely freed.