# # OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the # [OpenSSL](https://www.openssl.org/) library. # # # Examples # # All examples assume you have loaded OpenSSL with: # # require 'openssl' # # These examples build atop each other. For example the key created in the next # is used in throughout these examples. # # ## Keys # # ### Creating a Key # # This example creates a 2048 bit RSA keypair and writes it to the current # directory. # # key = OpenSSL::PKey::RSA.new 2048 # # open 'private_key.pem', 'w' do |io| io.write key.to_pem end # open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end # # ### Exporting a Key # # Keys saved to disk without encryption are not secure as anyone who gets ahold # of the key may use it unless it is encrypted. In order to securely export a # key you may export it with a pass phrase. # # cipher = OpenSSL::Cipher.new 'aes-256-cbc' # pass_phrase = 'my secure pass phrase goes here' # # key_secure = key.export cipher, pass_phrase # # open 'private.secure.pem', 'w' do |io| # io.write key_secure # end # # OpenSSL::Cipher.ciphers returns a list of available ciphers. # # ### Loading a Key # # A key can also be loaded from a file. # # key2 = OpenSSL::PKey.read File.read 'private_key.pem' # key2.public? # => true # key2.private? # => true # # or # # key3 = OpenSSL::PKey.read File.read 'public_key.pem' # key3.public? # => true # key3.private? # => false # # ### Loading an Encrypted Key # # OpenSSL will prompt you for your pass phrase when loading an encrypted key. If # you will not be able to type in the pass phrase you may provide it when # loading the key: # # key4_pem = File.read 'private.secure.pem' # pass_phrase = 'my secure pass phrase goes here' # key4 = OpenSSL::PKey.read key4_pem, pass_phrase # # ## RSA Encryption # # RSA provides encryption and decryption using the public and private keys. You # can use a variety of padding methods depending upon the intended use of # encrypted data. # # ### Encryption & Decryption # # Asymmetric public/private key encryption is slow and victim to attack in cases # where it is used without padding or directly to encrypt larger chunks of data. # Typical use cases for RSA encryption involve "wrapping" a symmetric key with # the public key of the recipient who would "unwrap" that symmetric key again # using their private key. The following illustrates a simplified example of # such a key transport scheme. It shouldn't be used in practice, though, # standardized protocols should always be preferred. # # wrapped_key = key.public_encrypt key # # A symmetric key encrypted with the public key can only be decrypted with the # corresponding private key of the recipient. # # original_key = key.private_decrypt wrapped_key # # By default PKCS#1 padding will be used, but it is also possible to use other # forms of padding, see PKey::RSA for further details. # # ### Signatures # # Using "private_encrypt" to encrypt some data with the private key is # equivalent to applying a digital signature to the data. A verifying party may # validate the signature by comparing the result of decrypting the signature # with "public_decrypt" to the original data. However, OpenSSL::PKey already has # methods "sign" and "verify" that handle digital signatures in a standardized # way - "private_encrypt" and "public_decrypt" shouldn't be used in practice. # # To sign a document, a cryptographically secure hash of the document is # computed first, which is then signed using the private key. # # signature = key.sign 'SHA256', document # # To validate the signature, again a hash of the document is computed and the # signature is decrypted using the public key. The result is then compared to # the hash just computed, if they are equal the signature was valid. # # if key.verify 'SHA256', signature, document # puts 'Valid' # else # puts 'Invalid' # end # # ## PBKDF2 Password-based Encryption # # If supported by the underlying OpenSSL version used, Password-based Encryption # should use the features of PKCS5. If not supported or if required by legacy # applications, the older, less secure methods specified in RFC 2898 are also # supported (see below). # # PKCS5 supports PBKDF2 as it was specified in PKCS#5 # [v2.0](http://www.rsa.com/rsalabs/node.asp?id=2127). It still uses a password, # a salt, and additionally a number of iterations that will slow the key # derivation process down. The slower this is, the more work it requires being # able to brute-force the resulting key. # # ### Encryption # # The strategy is to first instantiate a Cipher for encryption, and then to # generate a random IV plus a key derived from the password using PBKDF2. PKCS # #5 v2.0 recommends at least 8 bytes for the salt, the number of iterations # largely depends on the hardware being used. # # cipher = OpenSSL::Cipher.new 'aes-256-cbc' # cipher.encrypt # iv = cipher.random_iv # # pwd = 'some hopefully not to easily guessable password' # salt = OpenSSL::Random.random_bytes 16 # iter = 20000 # key_len = cipher.key_len # digest = OpenSSL::Digest.new('SHA256') # # key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) # cipher.key = key # # Now encrypt the data: # # encrypted = cipher.update document # encrypted << cipher.final # # ### Decryption # # Use the same steps as before to derive the symmetric AES key, this time # setting the Cipher up for decryption. # # cipher = OpenSSL::Cipher.new 'aes-256-cbc' # cipher.decrypt # cipher.iv = iv # the one generated with #random_iv # # pwd = 'some hopefully not to easily guessable password' # salt = ... # the one generated above # iter = 20000 # key_len = cipher.key_len # digest = OpenSSL::Digest.new('SHA256') # # key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) # cipher.key = key # # Now decrypt the data: # # decrypted = cipher.update encrypted # decrypted << cipher.final # # ## PKCS #5 Password-based Encryption # # PKCS #5 is a password-based encryption standard documented at # [RFC2898](http://www.ietf.org/rfc/rfc2898.txt). It allows a short password or # passphrase to be used to create a secure encryption key. If possible, PBKDF2 # as described above should be used if the circumstances allow it. # # PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption key. # # pass_phrase = 'my secure pass phrase goes here' # salt = '8 octets' # # ### Encryption # # First set up the cipher for encryption # # encryptor = OpenSSL::Cipher.new 'aes-256-cbc' # encryptor.encrypt # encryptor.pkcs5_keyivgen pass_phrase, salt # # Then pass the data you want to encrypt through # # encrypted = encryptor.update 'top secret document' # encrypted << encryptor.final # # ### Decryption # # Use a new Cipher instance set up for decryption # # decryptor = OpenSSL::Cipher.new 'aes-256-cbc' # decryptor.decrypt # decryptor.pkcs5_keyivgen pass_phrase, salt # # Then pass the data you want to decrypt through # # plain = decryptor.update encrypted # plain << decryptor.final # # ## X509 Certificates # # ### Creating a Certificate # # This example creates a self-signed certificate using an RSA key and a SHA1 # signature. # # key = OpenSSL::PKey::RSA.new 2048 # name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example' # # cert = OpenSSL::X509::Certificate.new # cert.version = 2 # cert.serial = 0 # cert.not_before = Time.now # cert.not_after = Time.now + 3600 # # cert.public_key = key.public_key # cert.subject = name # # ### Certificate Extensions # # You can add extensions to the certificate with OpenSSL::SSL::ExtensionFactory # to indicate the purpose of the certificate. # # extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert # # cert.add_extension \ # extension_factory.create_extension('basicConstraints', 'CA:FALSE', true) # # cert.add_extension \ # extension_factory.create_extension( # 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature') # # cert.add_extension \ # extension_factory.create_extension('subjectKeyIdentifier', 'hash') # # The list of supported extensions (and in some cases their possible values) can # be derived from the "objects.h" file in the OpenSSL source code. # # ### Signing a Certificate # # To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign # with a digest algorithm. This creates a self-signed cert because we're using # the same name and key to sign the certificate as was used to create the # certificate. # # cert.issuer = name # cert.sign key, OpenSSL::Digest.new('SHA1') # # open 'certificate.pem', 'w' do |io| io.write cert.to_pem end # # ### Loading a Certificate # # Like a key, a cert can also be loaded from a file. # # cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem' # # ### Verifying a Certificate # # Certificate#verify will return true when a certificate was signed with the # given public key. # # raise 'certificate can not be verified' unless cert2.verify key # # ## Certificate Authority # # A certificate authority (CA) is a trusted third party that allows you to # verify the ownership of unknown certificates. The CA issues key signatures # that indicate it trusts the user of that key. A user encountering the key can # verify the signature by using the CA's public key. # # ### CA Key # # CA keys are valuable, so we encrypt and save it to disk and make sure it is # not readable by other users. # # ca_key = OpenSSL::PKey::RSA.new 2048 # pass_phrase = 'my secure pass phrase goes here' # # cipher = OpenSSL::Cipher.new 'aes-256-cbc' # # open 'ca_key.pem', 'w', 0400 do |io| # io.write ca_key.export(cipher, pass_phrase) # end # # ### CA Certificate # # A CA certificate is created the same way we created a certificate above, but # with different extensions. # # ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example' # # ca_cert = OpenSSL::X509::Certificate.new # ca_cert.serial = 0 # ca_cert.version = 2 # ca_cert.not_before = Time.now # ca_cert.not_after = Time.now + 86400 # # ca_cert.public_key = ca_key.public_key # ca_cert.subject = ca_name # ca_cert.issuer = ca_name # # extension_factory = OpenSSL::X509::ExtensionFactory.new # extension_factory.subject_certificate = ca_cert # extension_factory.issuer_certificate = ca_cert # # ca_cert.add_extension \ # extension_factory.create_extension('subjectKeyIdentifier', 'hash') # # This extension indicates the CA's key may be used as a CA. # # ca_cert.add_extension \ # extension_factory.create_extension('basicConstraints', 'CA:TRUE', true) # # This extension indicates the CA's key may be used to verify signatures on both # certificates and certificate revocations. # # ca_cert.add_extension \ # extension_factory.create_extension( # 'keyUsage', 'cRLSign,keyCertSign', true) # # Root CA certificates are self-signed. # # ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1') # # The CA certificate is saved to disk so it may be distributed to all the users # of the keys this CA will sign. # # open 'ca_cert.pem', 'w' do |io| # io.write ca_cert.to_pem # end # # ### Certificate Signing Request # # The CA signs keys through a Certificate Signing Request (CSR). The CSR # contains the information necessary to identify the key. # # csr = OpenSSL::X509::Request.new # csr.version = 0 # csr.subject = name # csr.public_key = key.public_key # csr.sign key, OpenSSL::Digest.new('SHA1') # # A CSR is saved to disk and sent to the CA for signing. # # open 'csr.pem', 'w' do |io| # io.write csr.to_pem # end # # ### Creating a Certificate from a CSR # # Upon receiving a CSR the CA will verify it before signing it. A minimal # verification would be to check the CSR's signature. # # csr = OpenSSL::X509::Request.new File.read 'csr.pem' # # raise 'CSR can not be verified' unless csr.verify csr.public_key # # After verification a certificate is created, marked for various usages, signed # with the CA key and returned to the requester. # # csr_cert = OpenSSL::X509::Certificate.new # csr_cert.serial = 0 # csr_cert.version = 2 # csr_cert.not_before = Time.now # csr_cert.not_after = Time.now + 600 # # csr_cert.subject = csr.subject # csr_cert.public_key = csr.public_key # csr_cert.issuer = ca_cert.subject # # extension_factory = OpenSSL::X509::ExtensionFactory.new # extension_factory.subject_certificate = csr_cert # extension_factory.issuer_certificate = ca_cert # # csr_cert.add_extension \ # extension_factory.create_extension('basicConstraints', 'CA:FALSE') # # csr_cert.add_extension \ # extension_factory.create_extension( # 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature') # # csr_cert.add_extension \ # extension_factory.create_extension('subjectKeyIdentifier', 'hash') # # csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1') # # open 'csr_cert.pem', 'w' do |io| # io.write csr_cert.to_pem # end # # ## SSL and TLS Connections # # Using our created key and certificate we can create an SSL or TLS connection. # An SSLContext is used to set up an SSL session. # # context = OpenSSL::SSL::SSLContext.new # # ### SSL Server # # An SSL server requires the certificate and private key to communicate securely # with its clients: # # context.cert = cert # context.key = key # # Then create an SSLServer with a TCP server socket and the context. Use the # SSLServer like an ordinary TCP server. # # require 'socket' # # tcp_server = TCPServer.new 5000 # ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context # # loop do # ssl_connection = ssl_server.accept # # data = ssl_connection.gets # # response = "I got #{data.dump}" # puts response # # ssl_connection.puts "I got #{data.dump}" # ssl_connection.close # end # # ### SSL client # # An SSL client is created with a TCP socket and the context. SSLSocket#connect # must be called to initiate the SSL handshake and start encryption. A key and # certificate are not required for the client socket. # # Note that SSLSocket#close doesn't close the underlying socket by default. Set # SSLSocket#sync_close to true if you want. # # require 'socket' # # tcp_socket = TCPSocket.new 'localhost', 5000 # ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context # ssl_client.sync_close = true # ssl_client.connect # # ssl_client.puts "hello server!" # puts ssl_client.gets # # ssl_client.close # shutdown the TLS connection and close tcp_socket # # ### Peer Verification # # An unverified SSL connection does not provide much security. For enhanced # security the client or server can verify the certificate of its peer. # # The client can be modified to verify the server's certificate against the # certificate authority's certificate: # # context.ca_file = 'ca_cert.pem' # context.verify_mode = OpenSSL::SSL::VERIFY_PEER # # require 'socket' # # tcp_socket = TCPSocket.new 'localhost', 5000 # ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context # ssl_client.connect # # ssl_client.puts "hello server!" # puts ssl_client.gets # # If the server certificate is invalid or `context.ca_file` is not set when # verifying peers an OpenSSL::SSL::SSLError will be raised. # module OpenSSL # # Returns a Digest subclass by *name* # # require 'openssl' # # OpenSSL::Digest("MD5") # # => OpenSSL::Digest::MD5 # # Digest("Foo") # # => NameError: wrong constant name Foo # def self.Digest: (String name) -> singleton(Digest) # # def self.debug: () -> bool # # Turns on or off debug mode. With debug mode, all errors added to the OpenSSL # error queue will be printed to stderr. # def self.debug=: [U] (boolish) -> U # # See any remaining errors held in queue. # # Any errors you see here are probably due to a bug in Ruby's OpenSSL # implementation. # def self.errors: () -> Array[String] # # def self.fips_mode: () -> bool # # Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an # effect for FIPS-capable installations of the OpenSSL library. Trying to do so # otherwise will result in an error. # # ### Examples # OpenSSL.fips_mode = true # turn FIPS mode on # OpenSSL.fips_mode = false # and off again # def self.fips_mode=: [U] (boolish) -> U # # Constant time memory comparison for fixed length strings, such as results of # HMAC calculations. # # Returns `true` if the strings are identical, `false` if they are of the same # length but not identical. If the length is different, `ArgumentError` is # raised. # def self.fixed_length_secure_compare: (String, String) -> bool # # Constant time memory comparison. Inputs are hashed using SHA-256 to mask the # length of the secret. Returns `true` if the strings are identical, `false` # otherwise. # def self.secure_compare: (String a, String b) -> bool # # Boolean indicating whether OpenSSL is FIPS-capable or not # OPENSSL_FIPS: bool OPENSSL_LIBRARY_VERSION: String # # Version of OpenSSL the ruby OpenSSL extension was built with # OPENSSL_VERSION: String # # Version number of OpenSSL the ruby OpenSSL extension was built with (base 16) # OPENSSL_VERSION_NUMBER: Integer VERSION: String # # Abstract Syntax Notation One (or ASN.1) is a notation syntax to describe data # structures and is defined in ITU-T X.680. ASN.1 itself does not mandate any # encoding or parsing rules, but usually ASN.1 data structures are encoded using # the Distinguished Encoding Rules (DER) or less often the Basic Encoding Rules # (BER) described in ITU-T X.690. DER and BER encodings are binary # Tag-Length-Value (TLV) encodings that are quite concise compared to other # popular data description formats such as XML, JSON etc. ASN.1 data structures # are very common in cryptographic applications, e.g. X.509 public key # certificates or certificate revocation lists (CRLs) are all defined in ASN.1 # and DER-encoded. ASN.1, DER and BER are the building blocks of applied # cryptography. The ASN1 module provides the necessary classes that allow # generation of ASN.1 data structures and the methods to encode them using a DER # encoding. The decode method allows parsing arbitrary BER-/DER-encoded data to # a Ruby object that can then be modified and re-encoded at will. # # ## ASN.1 class hierarchy # # The base class representing ASN.1 structures is ASN1Data. ASN1Data offers # attributes to read and set the *tag*, the *tag_class* and finally the *value* # of a particular ASN.1 item. Upon parsing, any tagged values (implicit or # explicit) will be represented by ASN1Data instances because their "real type" # can only be determined using out-of-band information from the ASN.1 type # declaration. Since this information is normally known when encoding a type, # all sub-classes of ASN1Data offer an additional attribute *tagging* that # allows to encode a value implicitly (`:IMPLICIT`) or explicitly (`:EXPLICIT`). # # ### Constructive # # Constructive is, as its name implies, the base class for all constructed # encodings, i.e. those that consist of several values, opposed to "primitive" # encodings with just one single value. The value of an Constructive is always # an Array. # # #### ASN1::Set and ASN1::Sequence # # The most common constructive encodings are SETs and SEQUENCEs, which is why # there are two sub-classes of Constructive representing each of them. # # ### Primitive # # This is the super class of all primitive values. Primitive itself is not used # when parsing ASN.1 data, all values are either instances of a corresponding # sub-class of Primitive or they are instances of ASN1Data if the value was # tagged implicitly or explicitly. Please cf. Primitive documentation for # details on sub-classes and their respective mappings of ASN.1 data types to # Ruby objects. # # ## Possible values for *tagging* # # When constructing an ASN1Data object the ASN.1 type definition may require # certain elements to be either implicitly or explicitly tagged. This can be # achieved by setting the *tagging* attribute manually for sub-classes of # ASN1Data. Use the symbol `:IMPLICIT` for implicit tagging and `:EXPLICIT` if # the element requires explicit tagging. # # ## Possible values for *tag_class* # # It is possible to create arbitrary ASN1Data objects that also support a # PRIVATE or APPLICATION tag class. Possible values for the *tag_class* # attribute are: # * `:UNIVERSAL` (the default for untagged values) # * `:CONTEXT_SPECIFIC` (the default for tagged values) # * `:APPLICATION` # * `:PRIVATE` # # # ## Tag constants # # There is a constant defined for each universal tag: # * OpenSSL::ASN1::EOC (0) # * OpenSSL::ASN1::BOOLEAN (1) # * OpenSSL::ASN1::INTEGER (2) # * OpenSSL::ASN1::BIT_STRING (3) # * OpenSSL::ASN1::OCTET_STRING (4) # * OpenSSL::ASN1::NULL (5) # * OpenSSL::ASN1::OBJECT (6) # * OpenSSL::ASN1::ENUMERATED (10) # * OpenSSL::ASN1::UTF8STRING (12) # * OpenSSL::ASN1::SEQUENCE (16) # * OpenSSL::ASN1::SET (17) # * OpenSSL::ASN1::NUMERICSTRING (18) # * OpenSSL::ASN1::PRINTABLESTRING (19) # * OpenSSL::ASN1::T61STRING (20) # * OpenSSL::ASN1::VIDEOTEXSTRING (21) # * OpenSSL::ASN1::IA5STRING (22) # * OpenSSL::ASN1::UTCTIME (23) # * OpenSSL::ASN1::GENERALIZEDTIME (24) # * OpenSSL::ASN1::GRAPHICSTRING (25) # * OpenSSL::ASN1::ISO64STRING (26) # * OpenSSL::ASN1::GENERALSTRING (27) # * OpenSSL::ASN1::UNIVERSALSTRING (28) # * OpenSSL::ASN1::BMPSTRING (30) # # # ## UNIVERSAL_TAG_NAME constant # # An Array that stores the name of a given tag number. These names are the same # as the name of the tag constant that is additionally defined, e.g. # +[UNIVERSAL_TAG_NAME](2) = "INTEGER"+ and +OpenSSL::ASN1::INTEGER = 2+. # # ## Example usage # # ### Decoding and viewing a DER-encoded file # require 'openssl' # require 'pp' # der = File.binread('data.der') # asn1 = OpenSSL::ASN1.decode(der) # pp der # # ### Creating an ASN.1 structure and DER-encoding it # require 'openssl' # version = OpenSSL::ASN1::Integer.new(1) # # Explicitly 0-tagged implies context-specific tag class # serial = OpenSSL::ASN1::Integer.new(12345, 0, :EXPLICIT, :CONTEXT_SPECIFIC) # name = OpenSSL::ASN1::PrintableString.new('Data 1') # sequence = OpenSSL::ASN1::Sequence.new( [ version, serial, name ] ) # der = sequence.to_der # module ASN1 type tagging = :IMPLICIT | :EXPLICIT type tag_class = :UNIVERSAL | :CONTEXT_SPECIFIC | :APPLICATION | :PRIVATE def self.BMPString: (String value, ?bn tag, ?tagging tagging) -> BMPString def self.BitString: (String value, ?bn tag, ?tagging tagging) -> BitString def self.Boolean: (boolish value, ?bn tag, ?tagging tagging) -> Boolean def self.EndOfContent: () -> EndOfContent def self.Enumerated: (bn value, ?bn tag, ?tagging tagging) -> Enumerated def self.GeneralString: (String value, ?bn tag, ?tagging tagging) -> GeneralString def self.GeneralizedTime: (::Time value, ?bn tag, ?tagging tagging) -> GeneralizedTime def self.GraphicString: (String value, ?bn tag, ?tagging tagging) -> GraphicString def self.IA5String: (String value, ?bn tag, ?tagging tagging) -> IA5String def self.ISO64String: (String value, ?bn tag, ?tagging tagging) -> ISO64String def self.Integer: (bn value, ?bn tag, ?tagging tagging) -> Integer def self.Null: (nil) -> Null def self.NumericString: (String value, ?bn tag, ?tagging tagging) -> NumericString def self.ObjectId: (String value, ?bn tag, ?tagging tagging) -> ObjectId def self.OctetString: (String value, ?bn tag, ?tagging tagging) -> OctetString def self.PrintableString: (String value, ?bn tag, ?tagging tagging) -> PrintableString def self.Sequence: (Array[ASN1Data] value, ?bn tag, ?tagging tagging) -> Sequence def self.Set: (Array[ASN1Data] value, ?bn tag, ?tagging tagging) -> Set def self.T61String: (String value, ?bn tag, ?tagging tagging) -> T61String def self.UTCTime: (::Time value, ?bn tag, ?tagging tagging) -> UTCTime def self.UTF8String: (String value, ?bn tag, ?tagging tagging) -> UTF8String def self.UniversalString: (String value, ?bn tag, ?tagging tagging) -> UniversalString def self.VideotexString: (String value, ?bn tag, ?tagging tagging) -> VideotexString # # Decodes a BER- or DER-encoded value and creates an ASN1Data instance. *der* # may be a String or any object that features a `.to_der` method transforming it # into a BER-/DER-encoded String+ # # ## Example # der = File.binread('asn1data') # asn1 = OpenSSL::ASN1.decode(der) # def self.decode: (String | _ToDer der) -> ASN1Data # # Similar to #decode with the difference that #decode expects one distinct value # represented in *der*. #decode_all on the contrary decodes a sequence of # sequential BER/DER values lined up in *der* and returns them as an array. # # ## Example # ders = File.binread('asn1data_seq') # asn1_ary = OpenSSL::ASN1.decode_all(ders) # def self.decode_all: (String | _ToDer der) -> Array[ASN1Data] # # If a block is given, it prints out each of the elements encountered. Block # parameters are (in that order): # * depth: The recursion depth, plus one with each constructed value being # encountered (Integer) # * offset: Current byte offset (Integer) # * header length: Combined length in bytes of the Tag and Length headers. # (Integer) # * length: The overall remaining length of the entire data (Integer) # * constructed: Whether this value is constructed or not (Boolean) # * tag_class: Current tag class (Symbol) # * tag: The current tag number (Integer) # # # ## Example # der = File.binread('asn1data.der') # OpenSSL::ASN1.traverse(der) do | depth, offset, header_len, length, constructed, tag_class, tag| # puts "Depth: #{depth} Offset: #{offset} Length: #{length}" # puts "Header length: #{header_len} Tag: #{tag} Tag class: #{tag_class} Constructed: #{constructed}" # end # def self.traverse: (String | _ToDer der) { (::Integer, ::Integer, ::Integer, ::Integer, bool, tag_class, ::Integer) -> void } -> void BIT_STRING: Integer BMPSTRING: Integer BOOLEAN: Integer CHARACTER_STRING: Integer EMBEDDED_PDV: Integer ENUMERATED: Integer EOC: Integer EXTERNAL: Integer GENERALIZEDTIME: Integer GENERALSTRING: Integer GRAPHICSTRING: Integer IA5STRING: Integer INTEGER: Integer ISO64STRING: Integer NULL: Integer NUMERICSTRING: Integer OBJECT: Integer OBJECT_DESCRIPTOR: Integer OCTET_STRING: Integer PRINTABLESTRING: Integer REAL: Integer RELATIVE_OID: Integer SEQUENCE: Integer SET: Integer T61STRING: Integer UNIVERSALSTRING: Integer # # Array storing tag names at the tag's index. # UNIVERSAL_TAG_NAME: Array[untyped] UTCTIME: Integer UTF8STRING: Integer VIDEOTEXSTRING: Integer interface _ToDer def to_der: () -> String end # # The top-level class representing any ASN.1 object. When parsed by ASN1.decode, # tagged values are always represented by an instance of ASN1Data. # # ## The role of ASN1Data for parsing tagged values # # When encoding an ASN.1 type it is inherently clear what original type (e.g. # INTEGER, OCTET STRING etc.) this value has, regardless of its tagging. But # opposed to the time an ASN.1 type is to be encoded, when parsing them it is # not possible to deduce the "real type" of tagged values. This is why tagged # values are generally parsed into ASN1Data instances, but with a different # outcome for implicit and explicit tagging. # # ### Example of a parsed implicitly tagged value # # An implicitly 1-tagged INTEGER value will be parsed as an ASN1Data with # * *tag* equal to 1 # * *tag_class* equal to `:CONTEXT_SPECIFIC` # * *value* equal to a String that carries the raw encoding of the INTEGER. # # This implies that a subsequent decoding step is required to completely decode # implicitly tagged values. # # ### Example of a parsed explicitly tagged value # # An explicitly 1-tagged INTEGER value will be parsed as an ASN1Data with # * *tag* equal to 1 # * *tag_class* equal to `:CONTEXT_SPECIFIC` # * *value* equal to an Array with one single element, an instance of # OpenSSL::ASN1::Integer, i.e. the inner element is the non-tagged primitive # value, and the tagging is represented in the outer ASN1Data # # # ## Example - Decoding an implicitly tagged INTEGER # int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT) # implicit 0-tagged # seq = OpenSSL::ASN1::Sequence.new( [int] ) # der = seq.to_der # asn1 = OpenSSL::ASN1.decode(der) # # pp asn1 => #]> # raw_int = asn1.value[0] # # manually rewrite tag and tag class to make it an UNIVERSAL value # raw_int.tag = OpenSSL::ASN1::INTEGER # raw_int.tag_class = :UNIVERSAL # int2 = OpenSSL::ASN1.decode(raw_int) # puts int2.value # => 1 # # ## Example - Decoding an explicitly tagged INTEGER # int = OpenSSL::ASN1::Integer.new(1, 0, :EXPLICIT) # explicit 0-tagged # seq = OpenSSL::ASN1::Sequence.new( [int] ) # der = seq.to_der # asn1 = OpenSSL::ASN1.decode(der) # # pp asn1 => #]>]> # int2 = asn1.value[0].value[0] # puts int2.value # => 1 # class ASN1Data public # # Never `nil`. A boolean value indicating whether the encoding uses indefinite # length (in the case of parsing) or whether an indefinite length form shall be # used (in the encoding case). In DER, every value uses definite length form. # But in scenarios where large amounts of data need to be transferred it might # be desirable to have some kind of streaming support available. For example, # huge OCTET STRINGs are preferably sent in smaller-sized chunks, each at a # time. This is possible in BER by setting the length bytes of an encoding to # zero and by this indicating that the following value will be sent in chunks. # Indefinite length encodings are always constructed. The end of such a stream # of chunks is indicated by sending a EOC (End of Content) tag. SETs and # SEQUENCEs may use an indefinite length encoding, but also primitive types such # as e.g. OCTET STRINGS or BIT STRINGS may leverage this functionality (cf. # ITU-T X.690). # def indefinite_length: () -> bool # # Never `nil`. A boolean value indicating whether the encoding uses indefinite # length (in the case of parsing) or whether an indefinite length form shall be # used (in the encoding case). In DER, every value uses definite length form. # But in scenarios where large amounts of data need to be transferred it might # be desirable to have some kind of streaming support available. For example, # huge OCTET STRINGs are preferably sent in smaller-sized chunks, each at a # time. This is possible in BER by setting the length bytes of an encoding to # zero and by this indicating that the following value will be sent in chunks. # Indefinite length encodings are always constructed. The end of such a stream # of chunks is indicated by sending a EOC (End of Content) tag. SETs and # SEQUENCEs may use an indefinite length encoding, but also primitive types such # as e.g. OCTET STRINGS or BIT STRINGS may leverage this functionality (cf. # ITU-T X.690). # def indefinite_length=: [U] (boolish) -> U # # Never `nil`. A boolean value indicating whether the encoding uses indefinite # length (in the case of parsing) or whether an indefinite length form shall be # used (in the encoding case). In DER, every value uses definite length form. # But in scenarios where large amounts of data need to be transferred it might # be desirable to have some kind of streaming support available. For example, # huge OCTET STRINGs are preferably sent in smaller-sized chunks, each at a # time. This is possible in BER by setting the length bytes of an encoding to # zero and by this indicating that the following value will be sent in chunks. # Indefinite length encodings are always constructed. The end of such a stream # of chunks is indicated by sending a EOC (End of Content) tag. SETs and # SEQUENCEs may use an indefinite length encoding, but also primitive types such # as e.g. OCTET STRINGS or BIT STRINGS may leverage this functionality (cf. # ITU-T X.690). # alias infinite_length indefinite_length # # Never `nil`. A boolean value indicating whether the encoding uses indefinite # length (in the case of parsing) or whether an indefinite length form shall be # used (in the encoding case). In DER, every value uses definite length form. # But in scenarios where large amounts of data need to be transferred it might # be desirable to have some kind of streaming support available. For example, # huge OCTET STRINGs are preferably sent in smaller-sized chunks, each at a # time. This is possible in BER by setting the length bytes of an encoding to # zero and by this indicating that the following value will be sent in chunks. # Indefinite length encodings are always constructed. The end of such a stream # of chunks is indicated by sending a EOC (End of Content) tag. SETs and # SEQUENCEs may use an indefinite length encoding, but also primitive types such # as e.g. OCTET STRINGS or BIT STRINGS may leverage this functionality (cf. # ITU-T X.690). # alias infinite_length= indefinite_length= # # An Integer representing the tag number of this ASN1Data. Never `nil`. # def tag: () -> bn # # An Integer representing the tag number of this ASN1Data. Never `nil`. # def tag=: (::Integer) -> ::Integer | (BN) -> BN # # A Symbol representing the tag class of this ASN1Data. Never `nil`. See # ASN1Data for possible values. # def tag_class: () -> tag_class # # A Symbol representing the tag class of this ASN1Data. Never `nil`. See # ASN1Data for possible values. # def tag_class=: (tag_class) -> tag_class # # Encodes this ASN1Data into a DER-encoded String value. The result is # DER-encoded except for the possibility of indefinite length forms. Indefinite # length forms are not allowed in strict DER, so strictly speaking the result of # such an encoding would be a BER-encoding. # def to_der: () -> String # # Carries the value of a ASN.1 type. Please confer Constructive and Primitive # for the mappings between ASN.1 data types and Ruby classes. # def value: () -> untyped # # Carries the value of a ASN.1 type. Please confer Constructive and Primitive # for the mappings between ASN.1 data types and Ruby classes. # def value=: (untyped) -> untyped private # # *value*: Please have a look at Constructive and Primitive to see how Ruby # types are mapped to ASN.1 types and vice versa. # # *tag*: An Integer indicating the tag number. # # *tag_class*: A Symbol indicating the tag class. Please cf. ASN1 for possible # values. # # ## Example # asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42) # tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER # def initialize: (untyped value, ::Integer tag, tag_class tag_class) -> void end # # Generic error class for all errors raised in ASN1 and any of the classes # defined in it. # class ASN1Error < OpenSSL::OpenSSLError end class BMPString < OpenSSL::ASN1::Primitive end class BitString < OpenSSL::ASN1::Primitive public def unused_bits: () -> ::Integer def unused_bits=: (::Integer) -> ::Integer def value: () -> String def value=: (String) -> String end class Boolean < OpenSSL::ASN1::Primitive def value: () -> bool def value=: [U] (boolish) -> U end # # The parent class for all constructed encodings. The *value* attribute of a # Constructive is always an Array. Attributes are the same as for ASN1Data, with # the addition of *tagging*. # # ## SET and SEQUENCE # # Most constructed encodings come in the form of a SET or a SEQUENCE. These # encodings are represented by one of the two sub-classes of Constructive: # * OpenSSL::ASN1::Set # * OpenSSL::ASN1::Sequence # # Please note that tagged sequences and sets are still parsed as instances of # ASN1Data. Find further details on tagged values there. # # ### Example - constructing a SEQUENCE # int = OpenSSL::ASN1::Integer.new(1) # str = OpenSSL::ASN1::PrintableString.new('abc') # sequence = OpenSSL::ASN1::Sequence.new( [ int, str ] ) # # ### Example - constructing a SET # int = OpenSSL::ASN1::Integer.new(1) # str = OpenSSL::ASN1::PrintableString.new('abc') # set = OpenSSL::ASN1::Set.new( [ int, str ] ) # class Constructive < OpenSSL::ASN1::ASN1Data include Enumerable[ASN1Data] public # # Calls the given block once for each element in self, passing that element as # parameter *asn1*. If no block is given, an enumerator is returned instead. # # ## Example # asn1_ary.each do |asn1| # puts asn1 # end # def each: () ?{ (ASN1Data) -> void } -> self # # May be used as a hint for encoding a value either implicitly or explicitly by # setting it either to `:IMPLICIT` or to `:EXPLICIT`. *tagging* is not set when # a ASN.1 structure is parsed using OpenSSL::ASN1.decode. # def tagging: () -> tagging? # # May be used as a hint for encoding a value either implicitly or explicitly by # setting it either to `:IMPLICIT` or to `:EXPLICIT`. *tagging* is not set when # a ASN.1 structure is parsed using OpenSSL::ASN1.decode. # def tagging=: (tagging) -> tagging # # See ASN1Data#to_der for details. # def to_der: () -> String private # # *value*: is mandatory. # # *tag*: optional, may be specified for tagged values. If no *tag* is specified, # the UNIVERSAL tag corresponding to the Primitive sub-class is used by default. # # *tagging*: may be used as an encoding hint to encode a value either explicitly # or implicitly, see ASN1 for possible values. # # *tag_class*: if *tag* and *tagging* are `nil` then this is set to `:UNIVERSAL` # by default. If either *tag* or *tagging* are set then `:CONTEXT_SPECIFIC` is # used as the default. For possible values please cf. ASN1. # # ## Example # int = OpenSSL::ASN1::Integer.new(42) # zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT) # private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE) # def initialize: (Array[ASN1Data]) -> void end class EndOfContent < OpenSSL::ASN1::ASN1Data public def to_der: () -> String private def initialize: () -> void end class Enumerated < OpenSSL::ASN1::Primitive def value: () -> ::Integer def value=: (::Integer) -> ::Integer end class GeneralString < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class GeneralizedTime < OpenSSL::ASN1::Primitive def value: () -> Time def value=: (Time) -> Time end class GraphicString < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class IA5String < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class ISO64String < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class Integer < OpenSSL::ASN1::Primitive def value: () -> ::Integer def value=: (::Integer) -> ::Integer end class Null < OpenSSL::ASN1::Primitive def value: () -> nil def value=: (nil) -> nil end class NumericString < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end # # Represents the primitive object id for OpenSSL::ASN1 # class ObjectId < OpenSSL::ASN1::Primitive # # This adds a new ObjectId to the internal tables. Where *object_id* is the # numerical form, *short_name* is the short name, and *long_name* is the long # name. # # Returns `true` if successful. Raises an OpenSSL::ASN1::ASN1Error if it fails. # def self.register: (String object_id, String short_name, String ong_name) -> bool def value: () -> String def value=: (String) -> String public # # Returns `true` if *other_oid* is the same as *oid* # def ==: (ObjectId other) -> bool # # The long name of the ObjectId, as defined in . # def ln: () -> String? # # The long name of the ObjectId, as defined in . # alias long_name ln # # Returns a String representing the Object Identifier in the dot notation, e.g. # "1.2.3.4.5" # def oid: () -> String # # The short name of the ObjectId, as defined in . # alias short_name sn # # The short name of the ObjectId, as defined in . # def sn: () -> String? end class OctetString < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end # # The parent class for all primitive encodings. Attributes are the same as for # ASN1Data, with the addition of *tagging*. Primitive values can never be # encoded with indefinite length form, thus it is not possible to set the # *indefinite_length* attribute for Primitive and its sub-classes. # # ## Primitive sub-classes and their mapping to Ruby classes # * OpenSSL::ASN1::EndOfContent <=> *value* is always `nil` # * OpenSSL::ASN1::Boolean <=> *value* is `true` or `false` # * OpenSSL::ASN1::Integer <=> *value* is an OpenSSL::BN # * OpenSSL::ASN1::BitString <=> *value* is a String # * OpenSSL::ASN1::OctetString <=> *value* is a String # * OpenSSL::ASN1::Null <=> *value* is always `nil` # * OpenSSL::ASN1::Object <=> *value* is a String # * OpenSSL::ASN1::Enumerated <=> *value* is an OpenSSL::BN # * OpenSSL::ASN1::UTF8String <=> *value* is a String # * OpenSSL::ASN1::NumericString <=> *value* is a String # * OpenSSL::ASN1::PrintableString <=> *value* is a String # * OpenSSL::ASN1::T61String <=> *value* is a String # * OpenSSL::ASN1::VideotexString <=> *value* is a String # * OpenSSL::ASN1::IA5String <=> *value* is a String # * OpenSSL::ASN1::UTCTime <=> *value* is a Time # * OpenSSL::ASN1::GeneralizedTime <=> *value* is a Time # * OpenSSL::ASN1::GraphicString <=> *value* is a String # * OpenSSL::ASN1::ISO64String <=> *value* is a String # * OpenSSL::ASN1::GeneralString <=> *value* is a String # * OpenSSL::ASN1::UniversalString <=> *value* is a String # * OpenSSL::ASN1::BMPString <=> *value* is a String # # # ## OpenSSL::ASN1::BitString # # ### Additional attributes # *unused_bits*: if the underlying BIT STRING's length is a multiple of 8 then # *unused_bits* is 0. Otherwise *unused_bits* indicates the number of bits that # are to be ignored in the final octet of the BitString's *value*. # # ## OpenSSL::ASN1::ObjectId # # NOTE: While OpenSSL::ASN1::ObjectId.new will allocate a new ObjectId, it is # not typically allocated this way, but rather that are received from parsed # ASN1 encodings. # # ### Additional attributes # * *sn*: the short name as defined in . # * *ln*: the long name as defined in . # * *oid*: the object identifier as a String, e.g. "1.2.3.4.5" # * *short_name*: alias for *sn*. # * *long_name*: alias for *ln*. # # # ## Examples # With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class # constructor takes at least one parameter, the *value*. # # ### Creating EndOfContent # eoc = OpenSSL::ASN1::EndOfContent.new # # ### Creating any other Primitive # prim = .new(value) # being one of the sub-classes except EndOfContent # prim_zero_tagged_implicit = .new(value, 0, :IMPLICIT) # prim_zero_tagged_explicit = .new(value, 0, :EXPLICIT) # class Primitive < OpenSSL::ASN1::ASN1Data public # # May be used as a hint for encoding a value either implicitly or explicitly by # setting it either to `:IMPLICIT` or to `:EXPLICIT`. *tagging* is not set when # a ASN.1 structure is parsed using OpenSSL::ASN1.decode. # def tagging: () -> tagging? # # May be used as a hint for encoding a value either implicitly or explicitly by # setting it either to `:IMPLICIT` or to `:EXPLICIT`. *tagging* is not set when # a ASN.1 structure is parsed using OpenSSL::ASN1.decode. # def tagging=: (tagging) -> tagging # # See ASN1Data#to_der for details. # def to_der: () -> String private # # *value*: is mandatory. # # *tag*: optional, may be specified for tagged values. If no *tag* is specified, # the UNIVERSAL tag corresponding to the Primitive sub-class is used by default. # # *tagging*: may be used as an encoding hint to encode a value either explicitly # or implicitly, see ASN1 for possible values. # # *tag_class*: if *tag* and *tagging* are `nil` then this is set to `:UNIVERSAL` # by default. If either *tag* or *tagging* are set then `:CONTEXT_SPECIFIC` is # used as the default. For possible values please cf. ASN1. # # ## Example # int = OpenSSL::ASN1::Integer.new(42) # zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT) # private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE) # def initialize: (untyped value, ?Integer tag, ?tagging tagging) -> void end class PrintableString < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class Sequence < OpenSSL::ASN1::Constructive def value: () -> Array[ASN1Data] def value=: (Array[ASN1Data]) -> Array[ASN1Data] end class Set < OpenSSL::ASN1::Constructive end class T61String < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class UTCTime < OpenSSL::ASN1::Primitive def value: () -> Time def value=: (Time) -> Time end class UTF8String < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class UniversalString < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end class VideotexString < OpenSSL::ASN1::Primitive def value: () -> String def value=: (String) -> String end end type bn = BN | ::Integer class BN include Comparable # # Generates a random prime number of bit length *bits*. If *safe* is set to # `true`, generates a safe prime. If *add* is specified, generates a prime that # fulfills condition `p % add = rem`. # # ### Parameters # * *bits* - integer # * *safe* - boolean # * *add* - BN # * *rem* - BN # def self.generate_prime: (::Integer bits, ?boolish safe, ?bn add, ?bn rem) -> instance def self.pseudo_rand: (*untyped) -> untyped def self.pseudo_rand_range: (untyped) -> untyped # # Generates a cryptographically strong pseudo-random number of `bits`. # # See also the man page BN_rand(3). # def self.rand: (*untyped) -> untyped # # Generates a cryptographically strong pseudo-random number in the range # 0...`range`. # # See also the man page BN_rand_range(3). # def self.rand_range: (untyped) -> untyped public # # def %: (int) -> instance # # def *: (int) -> instance # # def **: (int) -> instance # # def +: (int) -> instance # # def +@: () -> instance # # def -: (int) -> instance # # def -@: () -> instance # # Division of OpenSSL::BN instances # def /: (int) -> [ instance, instance ] # # def <<: (int) -> instance # # alias <=> cmp # # Returns `true` only if *obj* has the same value as *bn*. Contrast this with # OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN. # def ==: (untyped) -> bool # # Returns `true` only if *obj* has the same value as *bn*. Contrast this with # OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN. # alias === == # # def >>: (int) -> int # # Tests bit *bit* in *bn* and returns `true` if set, `false` if not set. # def bit_set?: (int) -> bool # # def clear_bit!: (int) -> void # # def cmp: (Integer) -> Integer # # def coerce: (::Integer) -> Array[Integer] | (BN) -> Array[BN] # # def copy: (int) -> instance # # Returns `true` only if *obj* is a `OpenSSL::BN` with the same value as *bn*. # Contrast this with OpenSSL::BN#==, which performs type conversions. # def eql?: (untyped other) -> bool # # def gcd: (int) -> instance # # Returns a hash code for this object. # # See also Object#hash. # def hash: () -> Integer # # def lshift!: (int bits) -> self def mask_bits!: (int) -> void # # def mod_add: (int, int) -> instance # # def mod_exp: (int, int) -> instance # # def mod_inverse: (int) -> instance # # def mod_mul: (int, int) -> instance # # def mod_sqr: (int) -> instance # # def mod_sub: (int, int) -> instance # # def negative?: () -> bool # # def num_bits: () -> ::Integer # # def num_bytes: () -> ::Integer # # def odd?: () -> bool # # def one?: () -> bool # # def pretty_print: (untyped q) -> untyped # # Performs a Miller-Rabin probabilistic primality test for `bn`. # # **`checks` parameter is deprecated in version 3.0.** It has no effect. # def prime?: (?int checks) -> bool # # Performs a Miller-Rabin probabilistic primality test for `bn`. # # **Deprecated in version 3.0.** Use #prime? instead. # # `checks` and `trial_div` parameters no longer have any effect. # def prime_fasttest?: (?int checks, ?int trial_div) -> bool # # def rshift!: (int bits) -> self # # def set_bit!: (int bit) -> self # # def sqr: () -> instance # # def to_bn: () -> self # # def to_i: () -> ::Integer # # alias to_int to_i # # Returns the string representation of the bignum. # # BN.new can parse the encoded string to convert back into an OpenSSL::BN. # # `base` # : The format. Must be one of the following: # * `0` - MPI format. See the man page BN_bn2mpi(3) for details. # * `2` - Variable-length and big-endian binary encoding. The sign of the # bignum is ignored. # * `10` - Decimal number representation, with a leading '-' for a # negative bignum. # * `16` - Hexadeciaml number representation, with a leading '-' for a # negative bignum. # def to_s: () -> String | (0) -> String | (2) -> String | (10) -> String | (16) -> String | (int base) -> String # # def ucmp: (int bn2) -> ::Integer # # def zero?: () -> bool private # # Construct a new OpenSSL BIGNUM object. # # If `bn` is an Integer or OpenSSL::BN, a new instance of OpenSSL::BN # representing the same value is returned. See also Integer#to_bn for the # short-hand. # # If a String is given, the content will be parsed according to `base`. # # `string` # : The string to be parsed. # `base` # : The format. Must be one of the following: # * `0` - MPI format. See the man page BN_mpi2bn(3) for details. # * `2` - Variable-length and big-endian binary encoding of a positive # number. # * `10` - Decimal number representation, with a leading '-' for a # negative number. # * `16` - Hexadeciaml number representation, with a leading '-' for a # negative number. # def initialize: (instance) -> void | (int) -> void | (string) -> void | (string, 0 | 2 | 10 | 16) -> void # # def initialize_copy: (instance other) -> instance end # # Generic Error for all of OpenSSL::BN (big num) # class BNError < OpenSSL::OpenSSLError end # # OpenSSL IO buffering mix-in module. # # This module allows an OpenSSL::SSL::SSLSocket to behave like an IO. # # You typically won't use this module directly, you can see it implemented in # OpenSSL::SSL::SSLSocket. # module Buffering include Enumerable[untyped] public # # Writes *s* to the stream. *s* will be converted to a String using `.to_s` # method. # def <<: (String s) -> self # # Closes the SSLSocket and flushes any unwritten data. # def close: () -> void # # Executes the block for every line in the stream where lines are separated by # *eol*. # # See also #gets # def each: (?String eol) ?{ (String) -> void } -> void # # Calls the given block once for each byte in the stream. # def each_byte: () ?{ (Integer) -> void } -> void # # alias each_line each # # alias eof eof? # # Returns true if the stream is at file which means there is no more data to be # read. # def eof?: () -> bool # # Flushes buffered data to the SSLSocket. # def flush: () -> self # # Reads one character from the stream. Returns nil if called at end of file. # def getc: () -> String? # # Reads the next "line" from the stream. Lines are separated by *eol*. If # *limit* is provided the result will not be longer than the given number of # bytes. # # *eol* may be a String or Regexp. # # Unlike IO#gets the line read will not be assigned to +$_+. # # Unlike IO#gets the separator must be provided if a limit is provided. # def gets: (?String | Regexp eol, ?Integer limit) -> String? # # Writes *args* to the stream. # # See IO#print for full details. # def print: (*untyped args) -> nil # # Formats and writes to the stream converting parameters under control of the # format string. # # See Kernel#sprintf for format string details. # def printf: (String format_string, *untyped args) -> nil # # Writes *args* to the stream along with a record separator. # # See IO#puts for full details. # def puts: (*untyped args) -> nil # # Reads *size* bytes from the stream. If *buf* is provided it must reference a # string which will receive the data. # # See IO#read for full details. # def read: (?Integer? size, ?String buf) -> String? # # Reads at most *maxlen* bytes in the non-blocking manner. # # When no data can be read without blocking it raises OpenSSL::SSL::SSLError # extended by IO::WaitReadable or IO::WaitWritable. # # IO::WaitReadable means SSL needs to read internally so read_nonblock should be # called again when the underlying IO is readable. # # IO::WaitWritable means SSL needs to write internally so read_nonblock should # be called again after the underlying IO is writable. # # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows: # # # emulates blocking read (readpartial). # begin # result = ssl.read_nonblock(maxlen) # rescue IO::WaitReadable # IO.select([io]) # retry # rescue IO::WaitWritable # IO.select(nil, [io]) # retry # end # # Note that one reason that read_nonblock writes to the underlying IO is when # the peer requests a new TLS/SSL handshake. See openssl the FAQ for more # details. http://www.openssl.org/support/faq.html # # By specifying a keyword argument *exception* to `false`, you can indicate that # read_nonblock should not raise an IO::Wait*able exception, but return the # symbol `:wait_writable` or `:wait_readable` instead. At EOF, it will return # `nil` instead of raising EOFError. # def read_nonblock: (Integer maxlen, ?String buf, ?exception: true) -> String | (Integer maxlen, ?String buf, exception: false) -> (String | :wait_writable | :wait_readable | nil) # # Reads a one-character string from the stream. Raises an EOFError at end of # file. # def readchar: () -> String # # Reads a line from the stream which is separated by *eol*. # # Raises EOFError if at end of file. # def readline: (?String eol) -> String # # Reads lines from the stream which are separated by *eol*. # # See also #gets # def readlines: (?String eol) -> ::Array[String] # # Reads at most *maxlen* bytes from the stream. If *buf* is provided it must # reference a string which will receive the data. # # See IO#readpartial for full details. # def readpartial: (Integer maxlen, ?String buf) -> String # # The "sync mode" of the SSLSocket. # # See IO#sync for full details. # def sync: () -> bool # # The "sync mode" of the SSLSocket. # # See IO#sync for full details. # def sync=: (boolish) -> void # # Pushes character *c* back onto the stream such that a subsequent buffered # character read will return it. # # Unlike IO#getc multiple bytes may be pushed back onto the stream. # # Has no effect on unbuffered reads (such as #sysread). # def ungetc: (String c) -> String # # Writes *s* to the stream. If the argument is not a String it will be # converted using `.to_s` method. Returns the number of bytes written. # def write: (*_ToS s) -> Integer # # Writes *s* in the non-blocking manner. # # If there is buffered data, it is flushed first. This may block. # # write_nonblock returns number of bytes written to the SSL connection. # # When no data can be written without blocking it raises OpenSSL::SSL::SSLError # extended by IO::WaitReadable or IO::WaitWritable. # # IO::WaitReadable means SSL needs to read internally so write_nonblock should # be called again after the underlying IO is readable. # # IO::WaitWritable means SSL needs to write internally so write_nonblock should # be called again after underlying IO is writable. # # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows. # # # emulates blocking write. # begin # result = ssl.write_nonblock(str) # rescue IO::WaitReadable # IO.select([io]) # retry # rescue IO::WaitWritable # IO.select(nil, [io]) # retry # end # # Note that one reason that write_nonblock reads from the underlying IO is when # the peer requests a new TLS/SSL handshake. See the openssl FAQ for more # details. http://www.openssl.org/support/faq.html # # By specifying a keyword argument *exception* to `false`, you can indicate that # write_nonblock should not raise an IO::Wait*able exception, but return the # symbol `:wait_writable` or `:wait_readable` instead. # def write_nonblock: (_ToS s, ?exception: true) -> Integer | (_ToS s, exception: false) -> (Integer | :wait_writable | :wait_readable | nil) private # # Consumes *size* bytes from the buffer # def consume_rbuff: (?untyped size) -> untyped # # Writes *s* to the buffer. When the buffer is full or #sync is true the buffer # is flushed to the underlying socket. # def do_write: (untyped s) -> untyped # # Fills the buffer from the underlying SSLSocket # def fill_rbuff: () -> untyped # # Default size to read from or write to the SSLSocket for buffer operations. # BLOCK_SIZE: Integer # # A buffer which will retain binary encoding. # class Buffer < String BINARY: Encoding # # def <<: (String string) -> self # # alias concat << end end # # 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('--') # # 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 Cipher # # Returns the names of all available ciphers in an array. # def self.ciphers: () -> Array[String] public # # 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 Cipher#encrypt and setting Cipher#key= and # Cipher#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 Cipher#decrypt, Cipher#key=, Cipher#iv= and Cipher#auth_tag= # first. # def auth_data=: (String) -> String # # 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 # default length of 16 bytes or the length previously set by #auth_tag_len= will # be used. For maximum security, the longest possible should be chosen. # # The tag may only be retrieved after calling Cipher#final. # def auth_tag: (?Integer tag_len) -> String # # Sets the authentication tag to verify the integrity of the ciphertext. This # can be called only when the cipher supports AE. The tag must be set after # calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before calling # Cipher#final. After all decryption is performed, the tag is verified # automatically in the call to Cipher#final. # # For OCB mode, the tag length must be supplied with #auth_tag_len= beforehand. # def auth_tag=: (String) -> String # # Sets the length of the authentication tag to be generated or to be given for # AEAD ciphers that requires it as in input parameter. Note that not all AEAD # ciphers support this method. # # In OCB mode, the length must be supplied both when encrypting and when # decrypting, and must be before specifying an IV. # def auth_tag_len=: (Integer) -> Integer # # Indicated whether this Cipher instance uses an Authenticated Encryption mode. # def authenticated?: () -> bool # # Returns the size in bytes of the blocks on which this Cipher operates on. # def block_size: () -> Integer # # Initializes the Cipher for decryption. # # Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the # following methods: # # #key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen # : # # Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0). # def decrypt: () -> self # # Initializes the Cipher for encryption. # # Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the # following methods: # # #key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen # : # # Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1). # def encrypt: () -> self # # Returns the remaining data held in the cipher object. Further calls to # Cipher#update or Cipher#final will return garbage. This call should always be # made as the last call of an encryption or decryption operation, 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. # def final: () -> String # # 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 Cipher#random_iv to create a # secure random IV. # # Only call this method after calling Cipher#encrypt or Cipher#decrypt. # def iv=: (String iv) -> String # # Returns the expected length in bytes for an IV for this Cipher. # def iv_len: () -> Integer # # Sets the IV/nonce length of the Cipher. Normally block ciphers don't allow # changing the IV length, but some make use of IV for 'nonce'. You may need this # for interoperability with other applications. # def iv_len=: (Integer) -> Integer # # 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, Cipher#random_key may be used. # # Only call this method after calling Cipher#encrypt or Cipher#decrypt. # def key=: (String key) -> String # # Returns the key length in bytes of the Cipher. # def key_len: () -> Integer # # Sets the key length of the cipher. If the cipher is a fixed length cipher # then attempting to set the key length to any value other than the fixed value # is an error. # # Under normal circumstances you do not need to call this method (and probably # shouldn't). # # See EVP_CIPHER_CTX_set_key_length for further information. # def key_len=: (Integer) -> Integer # # Returns the name of the cipher which may differ slightly from the original # name provided. # def name: () -> String # # 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. # # See EVP_CIPHER_CTX_set_padding for further information. # def padding=: (Integer) -> Integer # # Generates and sets the key/IV based on a password. # # **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. # # ### Parameters # * *salt* must be an 8 byte string if provided. # * *iterations* is an integer with a default of 2048. # * *digest* is a Digest object that defaults to 'MD5' # # # A minimum of 1000 iterations is recommended. # def pkcs5_keyivgen: (String pass, ?String salt, ?Integer iterations, ?String digest) -> void # # Generate a random IV with OpenSSL::Random.random_bytes and sets it to the # cipher, and returns it. # # You must call #encrypt or #decrypt before calling this method. # def random_iv: () -> String # # Generate a random key with OpenSSL::Random.random_bytes and sets it to the # cipher, and returns it. # # You must call #encrypt or #decrypt before calling this method. # def random_key: () -> String # # Fully resets the internal state of the Cipher. By using this, the same Cipher # instance may be used several times for encryption or decryption tasks. # # Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1). # def reset: () -> self # # 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 Cipher#final should be additionally added to the result. # # If *buffer* is given, the encryption/decryption result will be written to it. # *buffer* will be resized automatically. # def update: (String data, ?String buffer) -> String private def ciphers: () -> Array[String] # # The string must contain a valid cipher name like "aes-256-cbc". # # A list of cipher names is available by calling OpenSSL::Cipher.ciphers. # def initialize: (String cipher_name) -> void # # def initialize_copy: (untyped) -> untyped class AES < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end class AES128 < OpenSSL::Cipher private def initialize: (?_ToS mode) -> void end class AES192 < OpenSSL::Cipher private def initialize: (?_ToS mode) -> void end class AES256 < OpenSSL::Cipher private def initialize: (?_ToS mode) -> void end class BF < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end class CAST5 < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end # # Deprecated. # # This class is only provided for backwards compatibility. Use OpenSSL::Cipher. # class Cipher < OpenSSL::Cipher end class CipherError < OpenSSL::OpenSSLError end class DES < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end class IDEA < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end class RC2 < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end class RC4 < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end class RC5 < OpenSSL::Cipher private def initialize: (*_ToS args) -> void end end # # 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. # # See also http://www.openssl.org/docs/apps/config.html # class Config include Enumerable[[ String, String, String ]] def self.load: (?_ToS filename) -> instance # # Parses a given *string* as a blob that contains configuration for OpenSSL. # def self.parse: (String string) -> instance # # Parses the configuration data read from *io* and returns the whole content as # a Hash. # def self.parse_config: (IO io) -> Hash[String, Hash[String, String]] public # # Gets all key-value pairs in a specific *section* from the current # configuration. # # Given the following configurating file being loaded: # # config = OpenSSL::Config.load('foo.cnf') # #=> # # puts config.to_s # #=> [ default ] # # foo=bar # # You can get a hash of the specific section like so: # # config['default'] # #=> {"foo"=>"bar"} # def []: (String section) -> Hash[String, String] # # *Deprecated in v2.2.0*. This method will be removed in a future release. # # Sets a specific *section* name with a Hash *pairs*. # # Given the following configuration being created: # # config = OpenSSL::Config.new # #=> # # config['default'] = {"foo"=>"bar","baz"=>"buz"} # #=> {"foo"=>"bar", "baz"=>"buz"} # puts config.to_s # #=> [ default ] # # foo=bar # # baz=buz # # It's important to note that this will essentially merge any of the keys in # *pairs* with the existing *section*. For example: # # config['default'] # #=> {"foo"=>"bar", "baz"=>"buz"} # config['default'] = {"foo" => "changed"} # #=> {"foo"=>"changed"} # config['default'] # #=> {"foo"=>"changed", "baz"=>"buz"} # def []=: (String section, _Each[[ String, String ]] pairs) -> _Each[[ String, String ]] # # *Deprecated in v2.2.0*. This method will be removed in a future release. # # Set the target *key* with a given *value* under a specific *section*. # # Given the following configurating file being loaded: # # config = OpenSSL::Config.load('foo.cnf') # #=> # # puts config.to_s # #=> [ default ] # # foo=bar # # You can set the value of *foo* under the *default* section to a new value: # # config.add_value('default', 'foo', 'buzz') # #=> "buzz" # puts config.to_s # #=> [ default ] # # foo=buzz # def add_value: (String section, untyped key, untyped value) -> untyped # # Retrieves the section and its pairs for the current configuration. # # config.each do |section, key, value| # # ... # end # def each: () { ([ String, String, String ] args0) -> void } -> self # # Gets the value of *key* from the given *section*. # # Given the following configurating file being loaded: # # config = OpenSSL::Config.load('foo.cnf') # #=> # # puts config.to_s # #=> [ default ] # # foo=bar # # You can get a specific value from the config if you know the *section* and # *key* like so: # # config.get_value('default','foo') # #=> "bar" # def get_value: (String section, String key) -> String? # # String representation of this configuration object, including the class name # and its sections. # def inspect: () -> String def section: (String name) -> Hash[String, String] # # Get the names of all sections in the current configuration. # def sections: () -> Array[String] # # Gets the parsable form of the current configuration. # # Given the following configuration being created: # # config = OpenSSL::Config.new # #=> # # config['default'] = {"foo"=>"bar","baz"=>"buz"} # #=> {"foo"=>"bar", "baz"=>"buz"} # puts config.to_s # #=> [ default ] # # foo=bar # # baz=buz # # You can parse get the serialized configuration using #to_s and then parse it # later: # # serialized_config = config.to_s # # much later... # new_config = OpenSSL::Config.parse(serialized_config) # #=> # # puts new_config # #=> [ default ] # foo=bar # baz=buz # def to_s: () -> String private # # Creates an instance of OpenSSL::Config from the content of the file specified # by *filename*. # # This can be used in contexts like OpenSSL::X509::ExtensionFactory.config= # # This can raise IO exceptions based on the access, or availability of the file. # A ConfigError exception may be raised depending on the validity of the data # being configured. # def initialize: (?_ToS filename) -> void # # def initialize_copy: (instance other) -> void # # The default system configuration file for OpenSSL. # DEFAULT_CONFIG_FILE: String end # # General error for openssl library configuration files. Including formatting, # parsing errors, etc. # class ConfigError < OpenSSL::OpenSSLError end # # OpenSSL::Digest allows you to compute message digests (sometimes # interchangeably called "hashes") of arbitrary data that are cryptographically # secure, i.e. a Digest implements a secure one-way function. # # One-way functions offer some useful properties. E.g. given two distinct inputs # the probability that both yield the same output is highly unlikely. Combined # with the fact that every message digest algorithm has a fixed-length output of # just a few bytes, digests are often used to create unique identifiers for # arbitrary data. A common example is the creation of a unique id for binary # documents that are stored in a database. # # Another useful characteristic of one-way functions (and thus the name) is that # given a digest there is no indication about the original data that produced # it, i.e. the only way to identify the original input is to "brute-force" # through every possible combination of inputs. # # These characteristics make one-way functions also ideal companions for public # key signature algorithms: instead of signing an entire document, first a hash # of the document is produced with a considerably faster message digest # algorithm and only the few bytes of its output need to be signed using the # slower public key algorithm. To validate the integrity of a signed document, # it suffices to re-compute the hash and verify that it is equal to that in the # signature. # # You can get a list of all digest algorithms supported on your system by # running this command in your terminal: # # openssl list -digest-algorithms # # Among the OpenSSL 1.1.1 supported message digest algorithms are: # * SHA224, SHA256, SHA384, SHA512, SHA512-224 and SHA512-256 # * SHA3-224, SHA3-256, SHA3-384 and SHA3-512 # * BLAKE2s256 and BLAKE2b512 # # # Each of these algorithms can be instantiated using the name: # # digest = OpenSSL::Digest.new('SHA256') # # "Breaking" a message digest algorithm means defying its one-way function # characteristics, i.e. producing a collision or finding a way to get to the # original data by means that are more efficient than brute-forcing etc. Most of # the supported digest algorithms can be considered broken in this sense, even # the very popular MD5 and SHA1 algorithms. Should security be your highest # concern, then you should probably rely on SHA224, SHA256, SHA384 or SHA512. # # ### Hashing a file # # data = File.binread('document') # sha256 = OpenSSL::Digest.new('SHA256') # digest = sha256.digest(data) # # ### Hashing several pieces of data at once # # data1 = File.binread('file1') # data2 = File.binread('file2') # data3 = File.binread('file3') # sha256 = OpenSSL::Digest.new('SHA256') # sha256 << data1 # sha256 << data2 # sha256 << data3 # digest = sha256.digest # # ### Reuse a Digest instance # # data1 = File.binread('file1') # sha256 = OpenSSL::Digest.new('SHA256') # digest1 = sha256.digest(data1) # # data2 = File.binread('file2') # sha256.reset # digest2 = sha256.digest(data2) # class Digest # # Return the hash value computed with *name* Digest. *name* is either the long # name or short name of a supported digest algorithm. # # ### Examples # # OpenSSL::Digest.digest("SHA256", "abc") # # which is equivalent to: # # OpenSSL::Digest.digest('SHA256', "abc") # def self.digest: (String name, String data) -> String public # # Not every message digest can be computed in one single pass. If a message # digest is to be computed from several subsequent sources, then each may be # passed individually to the Digest instance. # # ### Example # digest = OpenSSL::Digest.new('SHA256') # digest.update('First input') # digest << 'Second input' # equivalent to digest.update('Second input') # result = digest.digest # alias << update # # Returns the block length of the digest algorithm, i.e. the length in bytes of # an individual block. Most modern algorithms partition a message to be digested # into a sequence of fix-sized blocks that are processed consecutively. # # ### Example # digest = OpenSSL::Digest.new('SHA1') # puts digest.block_length # => 64 # def block_length: () -> Integer def digest: (?String data) -> String # # Returns the output size of the digest, i.e. the length in bytes of the final # message digest result. # # ### Example # digest = OpenSSL::Digest.new('SHA1') # puts digest.digest_length # => 20 # def digest_length: () -> Integer def hexdigest: () -> String # # Returns the sn of this Digest algorithm. # # ### Example # digest = OpenSSL::Digest.new('SHA512') # puts digest.name # => SHA512 # def name: () -> String # # Resets the Digest in the sense that any Digest#update that has been performed # is abandoned and the Digest is set to its initial state again. # def reset: () -> self # # Not every message digest can be computed in one single pass. If a message # digest is to be computed from several subsequent sources, then each may be # passed individually to the Digest instance. # # ### Example # digest = OpenSSL::Digest.new('SHA256') # digest.update('First input') # digest << 'Second input' # equivalent to digest.update('Second input') # result = digest.digest # def update: (String data) -> self private # # def finish: (*untyped) -> untyped # # Creates a Digest instance based on *string*, which is either the ln (long # name) or sn (short name) of a supported digest algorithm. # # If *data* (a String) is given, it is used as the initial input to the Digest # instance, i.e. # # digest = OpenSSL::Digest.new('sha256', 'digestdata') # # is equivalent to # # digest = OpenSSL::Digest.new('sha256') # digest.update('digestdata') # def initialize: (String name, ?String data) -> void # # def initialize_copy: (instance) -> void class Digest < OpenSSL::Digest end # # Generic Exception class that is raised if an error occurs during a Digest # operation. # class DigestError < OpenSSL::OpenSSLError end class MD4 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end class MD5 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end class RIPEMD160 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end class SHA1 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end class SHA224 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end class SHA256 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end class SHA384 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end class SHA512 < OpenSSL::Digest def self.digest: (String data) -> String def self.hexdigest: (String data) -> String private def initialize: (?String data) -> void end end # # This class is the access to openssl's ENGINE cryptographic module # implementation. # # See also, https://www.openssl.org/docs/crypto/engine.html # class Engine # # Fetches the engine as specified by the *id* String. # # OpenSSL::Engine.by_id("openssl") # => # # # See OpenSSL::Engine.engines for the currently loaded engines. # def self.by_id: (String name) -> instance # # It is only necessary to run cleanup when engines are loaded via # OpenSSL::Engine.load. However, running cleanup before exit is recommended. # # Note that this is needed and works only in OpenSSL < 1.1.0. # def self.cleanup: () -> void # # Returns an array of currently loaded engines. # def self.engines: () -> Array[instance] # # This method loads engines. If *name* is nil, then all builtin engines are # loaded. Otherwise, the given *name*, as a String, is loaded if available to # your runtime, and returns true. If *name* is not found, then nil is returned. # def self.load: (?String name) -> (true | nil) public # # Returns a new instance of OpenSSL::Cipher by *name*, if it is available in # this engine. # # An EngineError will be raised if the cipher is unavailable. # # e = OpenSSL::Engine.by_id("openssl") # => # # e.cipher("RC4") # => # # def cipher: (String cipher) -> Cipher # # Returns an array of command definitions for the current engine # def cmds: () -> Array[[ String, String, String ]] # # Sends the given *command* to this engine. # # Raises an EngineError if the command fails. # def ctrl_cmd: (String cmd, ?String value) -> self # # Returns a new instance of OpenSSL::Digest by *name*. # # Will raise an EngineError if the digest is unavailable. # # e = OpenSSL::Engine.by_id("openssl") # #=> # # e.digest("SHA1") # #=> # # e.digest("zomg") # #=> OpenSSL::Engine::EngineError: no such digest `zomg' # def digest: (String digest) -> Digest # # Releases all internal structural references for this engine. # # May raise an EngineError if the engine is unavailable # def finish: () -> nil # # Gets the id for this engine. # # OpenSSL::Engine.load # OpenSSL::Engine.engines #=> [#, ...] # OpenSSL::Engine.engines.first.id # #=> "rsax" # def id: () -> String # # Pretty prints this engine. # def inspect: () -> String # # Loads the given private key identified by *id* and *data*. # # An EngineError is raised of the OpenSSL::PKey is unavailable. # def load_private_key: (?String id, ?String data) -> PKey::PKey # # Loads the given public key identified by *id* and *data*. # # An EngineError is raised of the OpenSSL::PKey is unavailable. # def load_public_key: (?String id, ?String data) -> PKey::PKey # # Get the descriptive name for this engine. # # OpenSSL::Engine.load # OpenSSL::Engine.engines #=> [#, ...] # OpenSSL::Engine.engines.first.name # #=> "RSAX engine support" # def name: () -> String # # Set the defaults for this engine with the given *flag*. # # These flags are used to control combinations of algorithm methods. # # *flag* can be one of the following, other flags are available depending on # your OS. # # All flags # : 0xFFFF # No flags # : 0x0000 # # # See also # def set_default: (Integer flag) -> bool METHOD_ALL: Integer METHOD_CIPHERS: Integer METHOD_DH: Integer METHOD_DIGESTS: Integer METHOD_DSA: Integer METHOD_NONE: Integer METHOD_RAND: Integer METHOD_RSA: Integer # # This is the generic exception for OpenSSL::Engine related errors # class EngineError < OpenSSL::OpenSSLError end end # # This module contains configuration information about the SSL extension, for # example if socket support is enabled, or the host name TLS extension is # enabled. Constants in this module will always be defined, but contain `true` # or `false` values depending on the configuration of your OpenSSL installation. # module ExtConfig HAVE_TLSEXT_HOST_NAME: bool OPENSSL_NO_SOCK: bool end # # 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. # # ### HMAC-SHA256 using one-shot interface # # key = "key" # data = "message-to-be-authenticated" # mac = OpenSSL::HMAC.hexdigest("SHA256", key, data) # #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e" # # ### HMAC-SHA256 using incremental interface # # data1 = File.binread("file1") # data2 = File.binread("file2") # key = "key" # hmac = OpenSSL::HMAC.new(key, 'SHA256') # hmac << data1 # hmac << data2 # mac = hmac.digest # class HMAC # # Returns the authentication code as a binary string. The *digest* parameter # specifies the digest algorithm to use. This may be a String representing the # algorithm name or an instance of OpenSSL::Digest. # # ### Example # key = 'key' # data = 'The quick brown fox jumps over the lazy dog' # # hmac = OpenSSL::HMAC.digest('SHA1', key, data) # #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9" # def self.digest: (String | Digest algo, String key, String data) -> String # # Returns the authentication code as a hex-encoded string. The *digest* # parameter specifies the digest algorithm to use. This may be a String # representing the algorithm name or an instance of OpenSSL::Digest. # # ### Example # key = 'key' # data = 'The quick brown fox jumps over the lazy dog' # # hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data) # #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" # def self.hexdigest: (String | Digest algo, String key, String data) -> String public # # Returns *hmac* updated with the message to be authenticated. Can be called # repeatedly with chunks of the message. # # ### Example # # first_chunk = 'The quick brown fox jumps ' # second_chunk = 'over the lazy dog' # # instance.update(first_chunk) # #=> 5b9a8038a65d571076d97fe783989e52278a492a # instance.update(second_chunk) # #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 # alias << update # # Securely compare with another HMAC instance in constant time. # def ==: (instance other) -> bool # # Returns the authentication code an instance represents as a binary string. # # ### Example # instance = OpenSSL::HMAC.new('key', 'SHA1') # #=> f42bb0eeb018ebbd4597ae7213711ec60760843f # instance.digest # #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?" # def digest: () -> String # # Returns the authentication code an instance represents as a hex-encoded # string. # def hexdigest: () -> String # # Returns the authentication code as a hex-encoded string. The *digest* # parameter specifies the digest algorithm to use. This may be a String # representing the algorithm name or an instance of OpenSSL::Digest. # # ### Example # key = 'key' # data = 'The quick brown fox jumps over the lazy dog' # # hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data) # #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" # alias inspect hexdigest # # Returns *hmac* as it was when it was first initialized, with all processed # data cleared from it. # # ### Example # # data = "The quick brown fox jumps over the lazy dog" # instance = OpenSSL::HMAC.new('key', 'SHA1') # #=> f42bb0eeb018ebbd4597ae7213711ec60760843f # # instance.update(data) # #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 # instance.reset # #=> f42bb0eeb018ebbd4597ae7213711ec60760843f # def reset: () -> self # # Returns the authentication code as a hex-encoded string. The *digest* # parameter specifies the digest algorithm to use. This may be a String # representing the algorithm name or an instance of OpenSSL::Digest. # # ### Example # key = 'key' # data = 'The quick brown fox jumps over the lazy dog' # # hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data) # #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" # alias to_s hexdigest # # Returns *hmac* updated with the message to be authenticated. Can be called # repeatedly with chunks of the message. # # ### Example # # first_chunk = 'The quick brown fox jumps ' # second_chunk = 'over the lazy dog' # # instance.update(first_chunk) # #=> 5b9a8038a65d571076d97fe783989e52278a492a # instance.update(second_chunk) # #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 # def update: (String data) -> self private # # Returns an instance of OpenSSL::HMAC set with the key and digest algorithm to # be used. The instance represents the initial state of the message # authentication code before any data has been processed. To process data with # it, use the instance method #update with your data as an argument. # # ### Example # # key = 'key' # instance = OpenSSL::HMAC.new(key, 'SHA1') # #=> f42bb0eeb018ebbd4597ae7213711ec60760843f # instance.class # #=> OpenSSL::HMAC # # ### A note about comparisons # # Two instances can be securely compared with #== in constant time: # # other_instance = OpenSSL::HMAC.new('key', 'SHA1') # #=> f42bb0eeb018ebbd4597ae7213711ec60760843f # instance == other_instance # #=> true # def initialize: (String key, String | Digest digest) -> void # # def initialize_copy: (instance) -> void end # # 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. # # ### HMAC-SHA256 using one-shot interface # # key = "key" # data = "message-to-be-authenticated" # mac = OpenSSL::HMAC.hexdigest("SHA256", key, data) # #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e" # # ### HMAC-SHA256 using incremental interface # # data1 = File.binread("file1") # data2 = File.binread("file2") # key = "key" # hmac = OpenSSL::HMAC.new(key, 'SHA256') # hmac << data1 # hmac << data2 # mac = hmac.digest # class HMACError < OpenSSL::OpenSSLError end # # Provides functionality of various KDFs (key derivation function). # # KDF is typically used for securely deriving arbitrary length symmetric keys to # be used with an OpenSSL::Cipher from passwords. Another use case is for # storing passwords: Due to the ability to tweak the effort of computation by # increasing the iteration count, computation can be slowed down artificially in # order to render possible attacks infeasible. # # Currently, OpenSSL::KDF provides implementations for the following KDF: # # * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination # with HMAC # * scrypt # * HKDF # # # ## Examples # ### Generating a 128 bit key for a Cipher (e.g. AES) # pass = "secret" # salt = OpenSSL::Random.random_bytes(16) # iter = 20_000 # key_len = 16 # key = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, # length: key_len, hash: "sha1") # # ### Storing Passwords # pass = "secret" # # store this with the generated value # salt = OpenSSL::Random.random_bytes(16) # iter = 20_000 # hash = OpenSSL::Digest.new('SHA256') # len = hash.digest_length # # the final value to be stored # value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, # length: len, hash: hash) # # ## Important Note on Checking Passwords # When comparing passwords provided by the user with previously stored values, a # common mistake made is comparing the two values using "==". Typically, "==" # short-circuits on evaluation, and is therefore vulnerable to timing attacks. # The proper way is to use a method that always takes the same amount of time # when comparing two values, thus not leaking any information to potential # attackers. To do this, use `OpenSSL.fixed_length_secure_compare`. # module KDF # # HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as specified in # [RFC 5869](https://tools.ietf.org/html/rfc5869). # # New in OpenSSL 1.1.0. # # ### Parameters # *ikm* # : The input keying material. # *salt* # : The salt. # *info* # : The context and application specific information. # *length* # : The output length in octets. Must be <= `255 * HashLen`, where HashLen is # the length of the hash function output in octets. # *hash* # : The hash function. # # # ### Example # # The values from https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.1 # ikm = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*") # salt = ["000102030405060708090a0b0c"].pack("H*") # info = ["f0f1f2f3f4f5f6f7f8f9"].pack("H*") # p OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: 42, hash: "SHA256").unpack1("H*") # # => "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865" # def self.hkdf: (String ikm, salt: String, info: String, length: Integer, hash: String) -> String # # PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination with # HMAC. Takes *pass*, *salt* and *iterations*, and then derives a key of # *length* bytes. # # For more information about PBKDF2, see RFC 2898 Section 5.2 # (https://tools.ietf.org/html/rfc2898#section-5.2). # # ### Parameters # pass # : The passphrase. # salt # : The salt. Salts prevent attacks based on dictionaries of common passwords # and attacks based on rainbow tables. It is a public value that can be # safely stored along with the password (e.g. if the derived value is used # for password storage). # iterations # : The iteration count. This provides the ability to tune the algorithm. It # is better to use the highest count possible for the maximum resistance to # brute-force attacks. # length # : The desired length of the derived key in octets. # hash # : The hash algorithm used with HMAC for the PRF. May be a String # representing the algorithm name, or an instance of OpenSSL::Digest. # def self.pbkdf2_hmac: (String pass, salt: String, iterations: Integer, length: Integer, hash: String | Digest) -> String # # Derives a key from *pass* using given parameters with the scrypt # password-based key derivation function. The result can be used for password # storage. # # scrypt is designed to be memory-hard and more secure against brute-force # attacks using custom hardwares than alternative KDFs such as PBKDF2 or bcrypt. # # The keyword arguments *N*, *r* and *p* can be used to tune scrypt. RFC 7914 # (published on 2016-08, https://tools.ietf.org/html/rfc7914#section-2) states # that using values r=8 and p=1 appears to yield good results. # # See RFC 7914 (https://tools.ietf.org/html/rfc7914) for more information. # # ### Parameters # pass # : Passphrase. # salt # : Salt. # N # : CPU/memory cost parameter. This must be a power of 2. # r # : Block size parameter. # p # : Parallelization parameter. # length # : Length in octets of the derived key. # # # ### Example # pass = "password" # salt = SecureRandom.random_bytes(16) # dk = OpenSSL::KDF.scrypt(pass, salt: salt, N: 2**14, r: 8, p: 1, length: 32) # p dk #=> "\xDA\xE4\xE2...\x7F\xA1\x01T" # def self.scrypt: (String pass, salt: String, N: Integer, r: Integer, p: Integer, length: Integer) -> String private def hkdf: (*untyped) -> untyped def pbkdf2_hmac: (*untyped) -> untyped def scrypt: (*untyped) -> untyped # # Generic exception class raised if an error occurs in OpenSSL::KDF module. # class KDFError < OpenSSL::OpenSSLError end end module Marshal # # def self.included: (untyped base) -> untyped public # # def _dump: (untyped _level) -> untyped module ClassMethods public # # def _load: (untyped string) -> untyped end end # # OpenSSL::Netscape is a namespace for SPKI (Simple Public Key Infrastructure) # which implements Signed Public Key and Challenge. See [RFC # 2692](http://tools.ietf.org/html/rfc2692) and [RFC # 2693](http://tools.ietf.org/html/rfc2692) for details. # module Netscape # # A Simple Public Key Infrastructure implementation (pronounced "spooky"). The # structure is defined as # PublicKeyAndChallenge ::= SEQUENCE { # spki SubjectPublicKeyInfo, # challenge IA5STRING # } # # SignedPublicKeyAndChallenge ::= SEQUENCE { # publicKeyAndChallenge PublicKeyAndChallenge, # signatureAlgorithm AlgorithmIdentifier, # signature BIT STRING # } # # where the definitions of SubjectPublicKeyInfo and AlgorithmIdentifier can be # found in RFC5280. SPKI is typically used in browsers for generating a # public/private key pair and a subsequent certificate request, using the HTML # element. # # ## Examples # # ### Creating an SPKI # key = OpenSSL::PKey::RSA.new 2048 # spki = OpenSSL::Netscape::SPKI.new # spki.challenge = "RandomChallenge" # spki.public_key = key.public_key # spki.sign(key, OpenSSL::Digest.new('SHA256')) # #send a request containing this to a server generating a certificate # # ### Verifying an SPKI request # request = #... # spki = OpenSSL::Netscape::SPKI.new request # unless spki.verify(spki.public_key) # # signature is invalid # end # #proceed # class SPKI public # # Returns the challenge string associated with this SPKI. # def challenge: () -> String # # ### Parameters # * *str* - the challenge string to be set for this instance # # # Sets the challenge to be associated with the SPKI. May be used by the server, # e.g. to prevent replay. # def challenge=: (String) -> String # # Returns the public key associated with the SPKI, an instance of OpenSSL::PKey. # def public_key: () -> PKey::PKey # # ### Parameters # * *pub* - the public key to be set for this instance # # # Sets the public key to be associated with the SPKI, an instance of # OpenSSL::PKey. This should be the public key corresponding to the private key # used for signing the SPKI. # def public_key=: (PKey::PKey) -> PKey::PKey # # ### Parameters # * *key* - the private key to be used for signing this instance # * *digest* - the digest to be used for signing this instance # # # To sign an SPKI, the private key corresponding to the public key set for this # instance should be used, in addition to a digest algorithm in the form of an # OpenSSL::Digest. The private key should be an instance of OpenSSL::PKey. # def sign: (PKey::PKey key, Digest digest) -> instance # # Returns the DER encoding of this SPKI. # def to_der: () -> String # # Returns the PEM encoding of this SPKI. # def to_pem: () -> String # # Returns the PEM encoding of this SPKI. # alias to_s to_pem # # Returns a textual representation of this SPKI, useful for debugging purposes. # def to_text: () -> String # # ### Parameters # * *key* - the public key to be used for verifying the SPKI signature # # # Returns `true` if the signature is valid, `false` otherwise. To verify an # SPKI, the public key contained within the SPKI should be used. # def verify: (PKey::PKey key) -> bool private # # ### Parameters # * *request* - optional raw request, either in PEM or DER format. # def initialize: (?String request) -> void end # # Generic Exception class that is raised if an error occurs during an operation # on an instance of OpenSSL::Netscape::SPKI. # class SPKIError < OpenSSL::OpenSSLError end end # # OpenSSL::OCSP implements Online Certificate Status Protocol requests and # responses. # # Creating and sending an OCSP request requires a subject certificate that # contains an OCSP URL in an authorityInfoAccess extension and the issuer # certificate for the subject certificate. First, load the issuer and subject # certificates: # # subject = OpenSSL::X509::Certificate.new subject_pem # issuer = OpenSSL::X509::Certificate.new issuer_pem # # To create the request we need to create a certificate ID for the subject # certificate so the CA knows which certificate we are asking about: # # digest = OpenSSL::Digest.new('SHA1') # certificate_id = # OpenSSL::OCSP::CertificateId.new subject, issuer, digest # # Then create a request and add the certificate ID to it: # # request = OpenSSL::OCSP::Request.new # request.add_certid certificate_id # # Adding a nonce to the request protects against replay attacks but not all CA # process the nonce. # # request.add_nonce # # To submit the request to the CA for verification we need to extract the OCSP # URI from the subject certificate: # # ocsp_uris = subject.ocsp_uris # # require 'uri' # # ocsp_uri = URI ocsp_uris[0] # # To submit the request we'll POST the request to the OCSP URI (per RFC 2560). # Note that we only handle HTTP requests and don't handle any redirects in this # example, so this is insufficient for serious use. # # require 'net/http' # # http_response = # Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http| # http.post ocsp_uri.path, request.to_der, # 'content-type' => 'application/ocsp-request' # end # # response = OpenSSL::OCSP::Response.new http_response.body # response_basic = response.basic # # First we check if the response has a valid signature. Without a valid # signature we cannot trust it. If you get a failure here you may be missing a # system certificate store or may be missing the intermediate certificates. # # store = OpenSSL::X509::Store.new # store.set_default_paths # # unless response_basic.verify [], store then # raise 'response is not signed by a trusted certificate' # end # # The response contains the status information (success/fail). We can display # the status as a string: # # puts response.status_string #=> successful # # Next we need to know the response details to determine if the response matches # our request. First we check the nonce. Again, not all CAs support a nonce. # See Request#check_nonce for the meanings of the return values. # # p request.check_nonce basic_response #=> value from -1 to 3 # # Then extract the status information for the certificate from the basic # response. # # single_response = basic_response.find_response(certificate_id) # # unless single_response # raise 'basic_response does not have the status for the certificate' # end # # Then check the validity. A status issued in the future must be rejected. # # unless single_response.check_validity # raise 'this_update is in the future or next_update time has passed' # end # # case single_response.cert_status # when OpenSSL::OCSP::V_CERTSTATUS_GOOD # puts 'certificate is still valid' # when OpenSSL::OCSP::V_CERTSTATUS_REVOKED # puts "certificate has been revoked at #{single_response.revocation_time}" # when OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN # puts 'responder doesn't know about the certificate' # end # module OCSP # # (This flag is not used by OpenSSL 1.0.1g) # NOCASIGN: Integer # # Do not include certificates in the response # NOCERTS: Integer # # Do not verify the certificate chain on the response # NOCHAIN: Integer # # Do not make additional signing certificate checks # NOCHECKS: Integer # # (This flag is not used by OpenSSL 1.0.1g) # NODELEGATED: Integer # # Do not check trust # NOEXPLICIT: Integer # # Do not search certificates contained in the response for a signer # NOINTERN: Integer # # Do not check the signature on the response # NOSIGS: Integer # # Do not include producedAt time in response # NOTIME: Integer # # Do not verify the response at all # NOVERIFY: Integer # # Identify the response by signing the certificate key ID # RESPID_KEY: Integer # # Internal error in issuer # RESPONSE_STATUS_INTERNALERROR: Integer # # Illegal confirmation request # RESPONSE_STATUS_MALFORMEDREQUEST: Integer # # You must sign the request and resubmit # RESPONSE_STATUS_SIGREQUIRED: Integer # # Response has valid confirmations # RESPONSE_STATUS_SUCCESSFUL: Integer # # Try again later # RESPONSE_STATUS_TRYLATER: Integer # # Your request is unauthorized. # RESPONSE_STATUS_UNAUTHORIZED: Integer # # The certificate subject's name or other information changed # REVOKED_STATUS_AFFILIATIONCHANGED: Integer # # This CA certificate was revoked due to a key compromise # REVOKED_STATUS_CACOMPROMISE: Integer # # The certificate is on hold # REVOKED_STATUS_CERTIFICATEHOLD: Integer # # The certificate is no longer needed # REVOKED_STATUS_CESSATIONOFOPERATION: Integer # # The certificate was revoked due to a key compromise # REVOKED_STATUS_KEYCOMPROMISE: Integer # # The certificate was revoked for an unknown reason # REVOKED_STATUS_NOSTATUS: Integer # # The certificate was previously on hold and should now be removed from the CRL # REVOKED_STATUS_REMOVEFROMCRL: Integer # # The certificate was superseded by a new certificate # REVOKED_STATUS_SUPERSEDED: Integer # # The certificate was revoked for an unspecified reason # REVOKED_STATUS_UNSPECIFIED: Integer # # Do not verify additional certificates # TRUSTOTHER: Integer # # Indicates the certificate is not revoked but does not necessarily mean the # certificate was issued or that this response is within the certificate's # validity interval # V_CERTSTATUS_GOOD: Integer # # Indicates the certificate has been revoked either permanently or temporarily # (on hold). # V_CERTSTATUS_REVOKED: Integer # # Indicates the responder does not know about the certificate being requested. # V_CERTSTATUS_UNKNOWN: Integer # # The responder ID is based on the public key. # V_RESPID_KEY: Integer # # The responder ID is based on the key name. # V_RESPID_NAME: Integer type ocsp_status = Integer # # An OpenSSL::OCSP::BasicResponse contains the status of a certificate check # which is created from an OpenSSL::OCSP::Request. A BasicResponse is more # detailed than a Response. # class BasicResponse public # # Adds *nonce* to this response. If no nonce was provided a random nonce will # be added. # def add_nonce: (?String nonce) -> self # # Adds a certificate status for *certificate_id*. *status* is the status, and # must be one of these: # # * OpenSSL::OCSP::V_CERTSTATUS_GOOD # * OpenSSL::OCSP::V_CERTSTATUS_REVOKED # * OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN # # # *reason* and *revocation_time* can be given only when *status* is # OpenSSL::OCSP::V_CERTSTATUS_REVOKED. *reason* describes the reason for the # revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants. # *revocation_time* is the time when the certificate is revoked. # # *this_update* and *next_update* indicate the time at which the status is # verified to be correct and the time at or before which newer information will # be available, respectively. *next_update* is optional. # # *extensions* is an Array of OpenSSL::X509::Extension to be included in the # SingleResponse. This is also optional. # # Note that the times, *revocation_time*, *this_update* and *next_update* can be # specified in either of Integer or Time object. If they are Integer, it is # treated as the relative seconds from the current time. # def add_status: (CertificateId certificate_id, ocsp_status status, Integer? reason, Integer? revocation_time, ?Integer | Time this_update, ?Integer | Time next_update, ?Array[X509::Extension] extensions) -> self # # Copies the nonce from *request* into this response. Returns 1 on success and # 0 on failure. # def copy_nonce: (Request request) -> Integer # # Returns a SingleResponse whose CertId matches with *certificate_id*, or `nil` # if this BasicResponse does not contain it. # def find_response: (CertificateId certificate_id) -> SingleResponse? # # Returns an Array of SingleResponse for this BasicResponse. # def responses: () -> Array[SingleResponse] # # Signs this OCSP response using the *cert*, *key* and optional *digest*. This # behaves in the similar way as OpenSSL::OCSP::Request#sign. # # *flags* can include: # OpenSSL::OCSP::NOCERTS # : don't include certificates # OpenSSL::OCSP::NOTIME # : don't set producedAt # OpenSSL::OCSP::RESPID_KEY # : use signer's public key hash as responderID # def sign: (X509::Certificate cert, PKey::PKey key, ?Array[X509::Certificate] certs, ?Integer flags, ?Digest digest) -> self # # Returns an Array of statuses for this response. Each status contains a # CertificateId, the status (0 for good, 1 for revoked, 2 for unknown), the # reason for the status, the revocation time, the time of this update, the time # for the next update and a list of OpenSSL::X509::Extension. # # This should be superseded by BasicResponse#responses and #find_response that # return SingleResponse. # def status: () -> Integer # # Encodes this basic response into a DER-encoded string. # def to_der: () -> String # # Verifies the signature of the response using the given *certificates* and # *store*. This works in the similar way as OpenSSL::OCSP::Request#verify. # def verify: (Array[X509::Certificate] certs, X509::Store store, ?Integer flags) -> bool private # # Creates a new BasicResponse. If *der_string* is given, decodes *der_string* as # DER. # def initialize: (?String der) -> void # # def initialize_copy: (instance) -> void end # # An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so that a # status check can be performed. # class CertificateId public # # Compares this certificate id with *other* and returns `true` if they are the # same. # def cmp: (instance other) -> bool # # Compares this certificate id's issuer with *other* and returns `true` if they # are the same. # def cmp_issuer: (instance other) -> bool # # Returns the ln (long name) of the hash algorithm used to generate the # issuerNameHash and the issuerKeyHash values. # def hash_algorithm: () -> String # # Returns the issuerKeyHash of this certificate ID, the hash of the issuer's # public key. # def issuer_key_hash: () -> String # # Returns the issuerNameHash of this certificate ID, the hash of the issuer's # distinguished name calculated with the hashAlgorithm. # def issuer_name_hash: () -> String # # Returns the serial number of the certificate for which status is being # requested. # def serial: () -> Integer # # Encodes this certificate identifier into a DER-encoded string. # def to_der: () -> String private # # Creates a new OpenSSL::OCSP::CertificateId for the given *subject* and # *issuer* X509 certificates. The *digest* is a digest algorithm that is used # to compute the hash values. This defaults to SHA-1. # # If only one argument is given, decodes it as DER representation of a # certificate ID or generates certificate ID from the object that responds to # the to_der method. # def initialize: (String | ASN1::_ToDer der) -> void | (X509::Certificate subject, X509::Certificate issuer, ?Digest digest) -> void # # def initialize_copy: (instance) -> void end # # OCSP error class. # class OCSPError < OpenSSL::OpenSSLError end # # An OpenSSL::OCSP::Request contains the certificate information for determining # if a certificate has been revoked or not. A Request can be created for a # certificate or from a DER-encoded request created elsewhere. # class Request public # # Adds *certificate_id* to the request. # def add_certid: (CertificateId certificate_id) -> self # # Adds a *nonce* to the OCSP request. If no nonce is given a random one will be # generated. # # The nonce is used to prevent replay attacks but some servers do not support # it. # def add_nonce: (?String nonce) -> self # # Returns all certificate IDs in this request. # def certid: () -> Array[CertificateId] # # Checks the nonce validity for this request and *response*. # # The return value is one of the following: # # -1 # : nonce in request only. # 0 # : nonces both present and not equal. # 1 # : nonces present and equal. # 2 # : nonces both absent. # 3 # : nonce present in response only. # # # For most responses, clients can check *result* > 0. If a responder doesn't # handle nonces `result.nonzero?` may be necessary. A result of `0` is always # an error. # def check_nonce: (Response response) -> (-1 | 0 | 1 | 2 | 3) # # Signs this OCSP request using *cert*, *key* and optional *digest*. If *digest* # is not specified, SHA-1 is used. *certs* is an optional Array of additional # certificates which are included in the request in addition to the signer # certificate. Note that if *certs* is `nil` or not given, flag # OpenSSL::OCSP::NOCERTS is enabled. Pass an empty array to include only the # signer certificate. # # *flags* is a bitwise OR of the following constants: # # OpenSSL::OCSP::NOCERTS # : Don't include any certificates in the request. *certs* will be ignored. # def sign: (X509::Certificate cert, PKey::PKey key, ?Array[X509::Certificate] certs, ?Integer flags, ?Digest digest) -> self # # Returns `true` if the request is signed, `false` otherwise. Note that the # validity of the signature is **not** checked. Use #verify to verify that. # def signed?: () -> bool # # Returns this request as a DER-encoded string # def to_der: () -> String # # Verifies this request using the given *certificates* and *store*. # *certificates* is an array of OpenSSL::X509::Certificate, *store* is an # OpenSSL::X509::Store. # # Note that `false` is returned if the request does not have a signature. Use # #signed? to check whether the request is signed or not. # def verify: (Array[X509::Certificate] certs, X509::Store store, ?Integer flags) -> bool private # # Creates a new OpenSSL::OCSP::Request. The request may be created empty or # from a *request_der* string. # def initialize: (?String der) -> void # # def initialize_copy: (instance) -> void end # # An OpenSSL::OCSP::Response contains the status of a certificate check which is # created from an OpenSSL::OCSP::Request. # class Response # # Creates an OpenSSL::OCSP::Response from *status* and *basic_response*. # def self.create: (Integer status, ?BasicResponse response) -> instance public # # Returns a BasicResponse for this response # def basic: () -> BasicResponse? # # Returns the status of the response. # def status: () -> Integer # # Returns a status string for the response. # def status_string: () -> String # # Returns this response as a DER-encoded string. # def to_der: () -> String private # # Creates a new OpenSSL::OCSP::Response. The response may be created empty or # from a *response_der* string. # def initialize: (?String der) -> void # # def initialize_copy: (instance) -> void end # # An OpenSSL::OCSP::SingleResponse represents an OCSP SingleResponse structure, # which contains the basic information of the status of the certificate. # class SingleResponse public # # Returns the status of the certificate identified by the certid. The return # value may be one of these constant: # # * V_CERTSTATUS_GOOD # * V_CERTSTATUS_REVOKED # * V_CERTSTATUS_UNKNOWN # # # When the status is V_CERTSTATUS_REVOKED, the time at which the certificate was # revoked can be retrieved by #revocation_time. # def cert_status: () -> ocsp_status # # Returns the CertificateId for which this SingleResponse is. # def certid: () -> CertificateId # # Checks the validity of thisUpdate and nextUpdate fields of this # SingleResponse. This checks the current time is within the range thisUpdate to # nextUpdate. # # It is possible that the OCSP request takes a few seconds or the time is not # accurate. To avoid rejecting a valid response, this method allows the times to # be within *nsec* seconds of the current time. # # Some responders don't set the nextUpdate field. This may cause a very old # response to be considered valid. The *maxsec* parameter can be used to limit # the age of responses. # def check_validity: (?Integer nsec, ?Integer maxsec) -> bool # # def extensions: () -> Array[X509::Certificate] # # def next_update: () -> Time? # # def revocation_reason: () -> Integer? # # def revocation_time: () -> Time? # # def this_update: () -> Time # # Encodes this SingleResponse into a DER-encoded string. # def to_der: () -> String private # # Creates a new SingleResponse from *der_string*. # def initialize: (String der) -> void # # def initialize_copy: (instance) -> void end end # # Generic error, common for all classes under OpenSSL module # class OpenSSLError < StandardError end # # Defines a file format commonly used to store private keys with accompanying # public key certificates, protected with a password-based symmetric key. # class PKCS12 # # ### Parameters # * *pass* - string # * *name* - A string describing the key. # * *key* - Any PKey. # * *cert* - A X509::Certificate. # * The public_key portion of the certificate must contain a valid public # key. # * The not_before and not_after fields must be filled in. # # * *ca* - An optional array of X509::Certificate's. # * *key_pbe* - string # * *cert_pbe* - string # * *key_iter* - integer # * *mac_iter* - integer # * *keytype* - An integer representing an MSIE specific extension. # # # Any optional arguments may be supplied as `nil` to preserve the OpenSSL # defaults. # # See the OpenSSL documentation for PKCS12_create(). # def self.create: (String pass, String name, PKey::PKey key, X509::Certificate cert, ?Array[X509::Certificate]? ca, ?String? key_pbe, ?String? cert_pbe, ?Integer? key_iter, ?Integer? mac_iter, ?Integer? keytype) -> instance public def ca_certs: () -> Array[X509::Certificate]? def certificate: () -> X509::Certificate def key: () -> PKey::PKey # # def to_der: () -> String private # # ### Parameters # * *str* - Must be a DER encoded PKCS12 string. # * *pass* - string # def initialize: (?String der, ?String pass) -> void # # def initialize_copy: (instance) -> void class PKCS12Error < OpenSSL::OpenSSLError end end module PKCS5 def self.pbkdf2_hmac: (String pass, String salt, Integer iter, Integer keylen, String | Digest digest) -> String def self.pbkdf2_hmac_sha1: (String pass, String salt, Integer iter, Integer keylen) -> String private # # OpenSSL::PKCS5.pbkdf2_hmac has been renamed to OpenSSL::KDF.pbkdf2_hmac. This # method is provided for backwards compatibility. # def pbkdf2_hmac: (untyped pass, untyped salt, untyped iter, untyped keylen, untyped digest) -> untyped # # def pbkdf2_hmac_sha1: (untyped pass, untyped salt, untyped iter, untyped keylen) -> untyped end class PKCS7 # # def self.encrypt: (X509::Certificate certs, String data, ?Cipher cipher, ?Integer flags) -> instance # # def self.read_smime: (String) -> instance # # def self.sign: (X509::Certificate certs, PKey::PKey key, String data, ?OpenSSL::Cipher cipher, ?Integer flags) -> instance # # def self.write_smime: (instance pkcs7, ?String data, ?Integer flags) -> String public # # def add_certificate: (X509::Certificate cert) -> self # # def add_crl: (X509::CRL crl) -> self # # def add_data: (String data) -> self # # def add_recipient: (RecipientInfo recipient) -> self # # def add_signer: (SignerInfo signer) -> self # # def certificates: () -> Array[X509::Certificate]? # # def certificates=: (Array[X509::Certificate]) -> self # # def cipher=: (Cipher cipher) -> self # # def crls: () -> Array[X509::CRL]? # # def crls=: (Array[X509::CRL]) -> self def data: () -> String? # # alias data= add_data # # def decrypt: (PKey::PKey p1, ?PKey::PKey p2, ?PKey::PKey p3) -> String # # def detached: () -> bool # # def detached=: [U] (boolish) -> U # # def detached?: () -> bool def error_string: () -> String? def error_string=: (String) -> String # # def recipients: () -> Array[RecipientInfo] # # def signers: () -> Array[SignerInfo] # # def to_der: () -> String # # def to_pem: () -> String # # alias to_s to_pem # # def type: () -> String? # # def type=: (String) -> String # # def verify: (PKey::PKey p1, PKey::PKey p2, ?PKey::PKey p3, ?PKey::PKey p4) -> bool private # # Many methods in this class aren't documented. # def initialize: (?String der) -> void # # def initialize_copy: (instance) -> untyped BINARY: Integer DETACHED: Integer NOATTR: Integer NOCERTS: Integer NOCHAIN: Integer NOINTERN: Integer NOSIGS: Integer NOSMIMECAP: Integer NOVERIFY: Integer TEXT: Integer class PKCS7Error < OpenSSL::OpenSSLError end class RecipientInfo public # # def enc_key: () -> PKey::PKey # # def issuer: () -> X509::Name # # def serial: () -> Integer private # # def initialize: (X509::Certificate certificate) -> void end class SignerInfo public # # def issuer: () -> X509::Name # # def serial: () -> Integer # # def signed_time: () -> Time? private # # def initialize: (X509::Certificate certificate, PKey::PKey key, Digest digest) -> void end end # # ## Asymmetric Public Key Algorithms # # Asymmetric public key algorithms solve the problem of establishing and sharing # secret keys to en-/decrypt messages. The key in such an algorithm consists of # two parts: a public key that may be distributed to others and a private key # that needs to remain secret. # # Messages encrypted with a public key can only be decrypted by recipients that # are in possession of the associated private key. Since public key algorithms # are considerably slower than symmetric key algorithms (cf. OpenSSL::Cipher) # they are often used to establish a symmetric key shared between two parties # that are in possession of each other's public key. # # Asymmetric algorithms offer a lot of nice features that are used in a lot of # different areas. A very common application is the creation and validation of # digital signatures. To sign a document, the signatory generally uses a message # digest algorithm (cf. OpenSSL::Digest) to compute a digest of the document # that is then encrypted (i.e. signed) using the private key. Anyone in # possession of the public key may then verify the signature by computing the # message digest of the original document on their own, decrypting the signature # using the signatory's public key and comparing the result to the message # digest they previously computed. The signature is valid if and only if the # decrypted signature is equal to this message digest. # # The PKey module offers support for three popular public/private key # algorithms: # * RSA (OpenSSL::PKey::RSA) # * DSA (OpenSSL::PKey::DSA) # * Elliptic Curve Cryptography (OpenSSL::PKey::EC) # # Each of these implementations is in fact a sub-class of the abstract PKey # class which offers the interface for supporting digital signatures in the form # of PKey#sign and PKey#verify. # # ## Diffie-Hellman Key Exchange # # Finally PKey also features OpenSSL::PKey::DH, an implementation of the # Diffie-Hellman key exchange protocol based on discrete logarithms in finite # fields, the same basis that DSA is built on. The Diffie-Hellman protocol can # be used to exchange (symmetric) keys over insecure channels without needing # any prior joint knowledge between the participating parties. As the security # of DH demands relatively long "public keys" (i.e. the part that is overtly # transmitted between participants) DH tends to be quite slow. If security or # speed is your primary concern, OpenSSL::PKey::EC offers another implementation # of the Diffie-Hellman protocol. # module PKey # # Reads a DER or PEM encoded string from *string* or *io* and returns an # instance of the appropriate PKey class. # # ### Parameters # * *string* is a DER- or PEM-encoded string containing an arbitrary private # or public key. # * *io* is an instance of IO containing a DER- or PEM-encoded arbitrary # private or public key. # * *pwd* is an optional password in case *string* or *io* is an encrypted PEM # resource. # def self?.read: (String | IO pem, ?String password) -> PKey # # An implementation of the Diffie-Hellman key exchange protocol based on # discrete logarithms in finite fields, the same basis that DSA is built on. # # ### Accessor methods for the Diffie-Hellman parameters # DH#p # : The prime (an OpenSSL::BN) of the Diffie-Hellman parameters. # DH#g # : The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters. # DH#pub_key # : The per-session public key (an OpenSSL::BN) matching the private key. This # needs to be passed to DH#compute_key. # DH#priv_key # : The per-session private key, an OpenSSL::BN. # # # ### Example of a key exchange # # you may send the parameters (der) and own public key (pub1) publicly # # to the participating party # dh1 = OpenSSL::PKey::DH.new(2048) # der = dh1.to_der # pub1 = dh1.pub_key # # # the other party generates its per-session key pair # dhparams = OpenSSL::PKey::DH.new(der) # dh2 = OpenSSL::PKey.generate_key(dhparams) # pub2 = dh2.pub_key # # symm_key1 = dh1.compute_key(pub2) # symm_key2 = dh2.compute_key(pub1) # puts symm_key1 == symm_key2 # => true # class DH < OpenSSL::PKey::PKey include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods # # Creates a new DH instance from scratch by generating random parameters and a # key pair. # # See also OpenSSL::PKey.generate_parameters and OpenSSL::PKey.generate_key. # # `size` # : The desired key size in bits. # `generator` # : The generator. # def self.generate: (Integer size, ?Integer generator) -> instance public # # Returns a String containing a shared secret computed from the other party's # public value. # # This method is provided for backwards compatibility, and calls #derive # internally. # # ### Parameters # * *pub_bn* is a OpenSSL::BN, **not** the DH instance returned by # DH#public_key as that contains the DH parameters only. # def compute_key: (bn pub_bn) -> String # # Encodes this DH to its PEM encoding. Note that any existing per-session # public/private keys will **not** get encoded, just the Diffie-Hellman # parameters will be encoded. # def export: () -> String def g: () -> BN? # # Generates a private and public key unless a private key already exists. If # this DH instance was generated from public DH parameters (e.g. by encoding the # result of DH#public_key), then this method needs to be called first in order # to generate the per-session keys before performing the actual key exchange. # # **Deprecated in version 3.0**. This method is incompatible with OpenSSL 3.0.0 # or later. # # See also OpenSSL::PKey.generate_key. # # Example: # # DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later # dh0 = OpenSSL::PKey::DH.new(2048) # dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name) # dh.generate_key! # puts dh.private? # => true # puts dh0.pub_key == dh.pub_key #=> false # # # With OpenSSL::PKey.generate_key # dh0 = OpenSSL::PKey::DH.new(2048) # dh = OpenSSL::PKey.generate_key(dh0) # puts dh0.pub_key == dh.pub_key #=> false # def generate_key!: () -> self def p: () -> BN # # Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN # LEAK OUT!!! Don't use :-)) (I's up to you) # def params: () -> Hash[String, BN] # # Validates the Diffie-Hellman parameters associated with this instance. It # checks whether a safe prime and a suitable generator are used. If this is not # the case, `false` is returned. # # See also the man page EVP_PKEY_param_check(3). # def params_ok?: () -> bool def priv_key: () -> BN # # Indicates whether this DH instance has a private key associated with it or # not. The private key may be retrieved with DH#priv_key. # def private?: () -> bool def pub_key: () -> BN # # Indicates whether this DH instance has a public key associated with it or not. # The public key may be retrieved with DH#pub_key. # def public?: () -> bool # # Returns a new DH instance that carries just the DH parameters. # # Contrary to the method name, the returned DH object contains only parameters # and not the public key. # # This method is provided for backwards compatibility. In most cases, there is # no need to call this method. # # For the purpose of re-generating the key pair while keeping the parameters, # check OpenSSL::PKey.generate_key. # # Example: # # OpenSSL::PKey::DH.generate by default generates a random key pair # dh1 = OpenSSL::PKey::DH.generate(2048) # p dh1.priv_key #=> # # dhcopy = dh1.public_key # p dhcopy.priv_key #=> nil # def public_key: () -> instance def q: () -> BN # # Sets *pub_key* and *priv_key* for the DH instance. *priv_key* may be `nil`. # def set_key: (bn pub_key, bn? priv_key) -> self # # Sets *p*, *q*, *g* to the DH instance. # def set_pqg: (bn p, bn q, bn g) -> self # # Encodes this DH to its DER encoding. Note that any existing per-session # public/private keys will **not** get encoded, just the Diffie-Hellman # parameters will be encoded. # def to_der: () -> String # # Encodes this DH to its PEM encoding. Note that any existing per-session # public/private keys will **not** get encoded, just the Diffie-Hellman # parameters will be encoded. # alias to_pem export # # Encodes this DH to its PEM encoding. Note that any existing per-session # public/private keys will **not** get encoded, just the Diffie-Hellman # parameters will be encoded. # alias to_s export # # Prints all parameters of key to buffer INSECURE: PRIVATE INFORMATIONS CAN LEAK # OUT!!! Don't use :-)) (I's up to you) # def to_text: () -> String private # # Creates a new instance of OpenSSL::PKey::DH. # # If called without arguments, an empty instance without any parameter or key # components is created. Use #set_pqg to manually set the parameters afterwards # (and optionally #set_key to set private and public key components). # # If a String is given, tries to parse it as a DER- or PEM- encoded parameters. # See also OpenSSL::PKey.read which can parse keys of any kinds. # # The DH.new(size [, generator]) form is an alias of DH.generate. # # `string` # : A String that contains the DER or PEM encoded key. # `size` # : See DH.generate. # `generator` # : See DH.generate. # # # Examples: # # Creating an instance from scratch # # Note that this is deprecated and will not work on OpenSSL 3.0 or later. # dh = OpenSSL::PKey::DH.new # dh.set_pqg(bn_p, nil, bn_g) # # # Generating a parameters and a key pair # dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048) # # # Reading DH parameters # dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only # dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair # def initialize: (Integer size, ?Integer generator) -> void | (String pem) -> void | () -> void # # def initialize_copy: (instance) -> void end # # Generic exception that is raised if an operation on a DH PKey fails # unexpectedly or in case an instantiation of an instance of DH fails due to # non-conformant input data. # class DHError < OpenSSL::PKey::PKeyError end # # DSA, the Digital Signature Algorithm, is specified in NIST's FIPS 186-3. It is # an asymmetric public key algorithm that may be used similar to e.g. RSA. # class DSA < OpenSSL::PKey::PKey include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods # # Creates a new DSA instance by generating a private/public key pair from # scratch. # # See also OpenSSL::PKey.generate_parameters and OpenSSL::PKey.generate_key. # # `size` # : The desired key size in bits. # def self.generate: (Integer size) -> instance public # # Encodes this DSA to its PEM encoding. # # ### Parameters # * *cipher* is an OpenSSL::Cipher. # * *password* is a string containing your password. # # # ### Examples # DSA.to_pem -> aString # DSA.to_pem(cipher, 'mypassword') -> aString # def export: (String cipher, String password) -> String | () -> String def g: () -> BN def p: () -> BN # # Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN # LEAK OUT!!! Don't use :-)) (I's up to you) # def params: () -> Hash[String, BN] def priv_key: () -> BN # # Indicates whether this DSA instance has a private key associated with it or # not. The private key may be retrieved with DSA#private_key. # def private?: () -> bool def pub_key: () -> BN # # Indicates whether this DSA instance has a public key associated with it or # not. The public key may be retrieved with DSA#public_key. # def public?: () -> bool # # Returns a new DSA instance that carries just the DSA parameters and the public # key. # # This method is provided for backwards compatibility. In most cases, there is # no need to call this method. # # For the purpose of serializing the public key, to PEM or DER encoding of X.509 # SubjectPublicKeyInfo format, check PKey#public_to_pem and PKey#public_to_der. # def public_key: () -> instance def q: () -> BN # # Sets *pub_key* and *priv_key* for the DSA instance. *priv_key* may be `nil`. # def set_key: (bn pub_key, bn? priv_key) -> self # # Sets *p*, *q*, *g* to the DSA instance. # def set_pqg: (bn p, bn q, bn g) -> self # # Computes and returns the DSA signature of `string`, where `string` is expected # to be an already-computed message digest of the original input data. The # signature is issued using the private key of this DSA instance. # # **Deprecated in version 3.0**. Consider using PKey::PKey#sign_raw and # PKey::PKey#verify_raw instead. # # `string` # : A message digest of the original input data to be signed. # # # Example: # dsa = OpenSSL::PKey::DSA.new(2048) # doc = "Sign me" # digest = OpenSSL::Digest.digest('SHA1', doc) # # # With legacy #syssign and #sysverify: # sig = dsa.syssign(digest) # p dsa.sysverify(digest, sig) #=> true # # # With #sign_raw and #verify_raw: # sig = dsa.sign_raw(nil, digest) # p dsa.verify_raw(nil, sig, digest) #=> true # def syssign: (String digest) -> String # # Verifies whether the signature is valid given the message digest input. It # does so by validating `sig` using the public key of this DSA instance. # # **Deprecated in version 3.0**. Consider using PKey::PKey#sign_raw and # PKey::PKey#verify_raw instead. # # `digest` # : A message digest of the original input data to be signed. # `sig` # : A DSA signature value. # def sysverify: (String digest, String data) -> bool # # Encodes this DSA to its DER encoding. # def to_der: () -> String # # Encodes this DSA to its PEM encoding. # # ### Parameters # * *cipher* is an OpenSSL::Cipher. # * *password* is a string containing your password. # # # ### Examples # DSA.to_pem -> aString # DSA.to_pem(cipher, 'mypassword') -> aString # alias to_pem export # # Encodes this DSA to its PEM encoding. # # ### Parameters # * *cipher* is an OpenSSL::Cipher. # * *password* is a string containing your password. # # # ### Examples # DSA.to_pem -> aString # DSA.to_pem(cipher, 'mypassword') -> aString # alias to_s export # # Prints all parameters of key to buffer INSECURE: PRIVATE INFORMATIONS CAN LEAK # OUT!!! Don't use :-)) (I's up to you) # def to_text: () -> String private # # Creates a new DSA instance by reading an existing key from *string*. # # If called without arguments, creates a new instance with no key components # set. They can be set individually by #set_pqg and #set_key. # # If called with a String, tries to parse as DER or PEM encoding of a DSA key. # See also OpenSSL::PKey.read which can parse keys of any kinds. # # If called with a number, generates random parameters and a key pair. This form # works as an alias of DSA.generate. # # `string` # : A String that contains a DER or PEM encoded key. # `pass` # : A String that contains an optional password. # `size` # : See DSA.generate. # # # Examples: # p OpenSSL::PKey::DSA.new(1024) # #=> # # # p OpenSSL::PKey::DSA.new(File.read('dsa.pem')) # #=> # # # p OpenSSL::PKey::DSA.new(File.read('dsa.pem'), 'mypassword') # #=> # # def initialize: (String pem, ?String pass) -> void | (?Integer size) -> void # # def initialize_copy: (instance) -> void end # # Generic exception that is raised if an operation on a DSA PKey fails # unexpectedly or in case an instantiation of an instance of DSA fails due to # non-conformant input data. # class DSAError < OpenSSL::PKey::PKeyError end # # OpenSSL::PKey::EC provides access to Elliptic Curve Digital Signature # Algorithm (ECDSA) and Elliptic Curve Diffie-Hellman (ECDH). # # ### Key exchange # ec1 = OpenSSL::PKey::EC.generate("prime256v1") # ec2 = OpenSSL::PKey::EC.generate("prime256v1") # # ec1 and ec2 have own private key respectively # shared_key1 = ec1.dh_compute_key(ec2.public_key) # shared_key2 = ec2.dh_compute_key(ec1.public_key) # # p shared_key1 == shared_key2 #=> true # class EC < OpenSSL::PKey::PKey include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods # # Obtains a list of all predefined curves by the OpenSSL. Curve names are # returned as sn. # # See the OpenSSL documentation for EC_get_builtin_curves(). # def self.builtin_curves: () -> Array[[ String, String ]] # # Creates a new EC instance with a new random private and public key. # def self.generate: (String | Group pem_or_der_or_group_or_curve_name) -> instance public # # Raises an exception if the key is invalid. # # See also the man page EVP_PKEY_public_check(3). # def check_key: () -> true # # Derives a shared secret by ECDH. *pubkey* must be an instance of # OpenSSL::PKey::EC::Point and must belong to the same group. # # This method is provided for backwards compatibility, and calls #derive # internally. # def dh_compute_key: (Point public_key) -> String # # **Deprecated in version 3.0**. Consider using PKey::PKey#sign_raw and # PKey::PKey#verify_raw instead. # def dsa_sign_asn1: (String digest) -> String # # **Deprecated in version 3.0**. Consider using PKey::PKey#sign_raw and # PKey::PKey#verify_raw instead. # def dsa_verify_asn1: (String digest, String signature) -> bool # # Outputs the EC key in PEM encoding. If *cipher* and *pass_phrase* are given # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher # instance. Note that encryption will only be effective for a private key, # public keys will always be encoded in plain text. # def export: (String cipher, String password) -> String | () -> String # # Generates a new random private and public key. # # See also the OpenSSL documentation for EC_KEY_generate_key() # # ### Example # ec = OpenSSL::PKey::EC.new("prime256v1") # p ec.private_key # => nil # ec.generate_key! # p ec.private_key # => # # alias generate_key generate_key! # # Generates a new random private and public key. # # See also the OpenSSL documentation for EC_KEY_generate_key() # # ### Example # ec = OpenSSL::PKey::EC.new("prime256v1") # p ec.private_key # => nil # ec.generate_key! # p ec.private_key # => # # def generate_key!: () -> self # # Returns the EC::Group that the key is associated with. Modifying the returned # group does not affect *key*. # def group: () -> Group? # # Sets the EC::Group for the key. The group structure is internally copied so # modification to *group* after assigning to a key has no effect on the key. # def group=: (Group) -> Group # # Returns whether this EC instance has a private key. The private key (BN) can # be retrieved with EC#private_key. # def private?: () -> bool # # See the OpenSSL documentation for EC_KEY_get0_private_key() # def private_key: () -> BN? # # See the OpenSSL documentation for EC_KEY_set_private_key() # def private_key=: (bn priv_key) -> self # # Returns whether this EC instance has a private key. The private key (BN) can # be retrieved with EC#private_key. # alias private_key? private? # # Returns whether this EC instance has a public key. The public key (EC::Point) # can be retrieved with EC#public_key. # def public?: () -> bool # # See the OpenSSL documentation for EC_KEY_get0_public_key() # def public_key: () -> Point? # # See the OpenSSL documentation for EC_KEY_set_public_key() # def public_key=: (bn priv_key) -> self # # Returns whether this EC instance has a public key. The public key (EC::Point) # can be retrieved with EC#public_key. # alias public_key? public? # # See the OpenSSL documentation for i2d_ECPrivateKey_bio() # def to_der: () -> String # # Outputs the EC key in PEM encoding. If *cipher* and *pass_phrase* are given # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher # instance. Note that encryption will only be effective for a private key, # public keys will always be encoded in plain text. # alias to_pem export # # See the OpenSSL documentation for EC_KEY_print() # def to_text: () -> String private # # Creates a new EC object from given arguments. # def initialize: () -> void | (instance ec_key) -> void | (Group group) -> void | (String pem_or_der_or_curve, ?String pass) -> void # # def initialize_copy: (instance) -> void EXPLICIT_CURVE: Integer NAMED_CURVE: Integer type ec_method = :GFp_simple | :GFp_mont | :GFp_nist | :GF2m_simple type point_conversion_format = :compressed | :uncompressed | :hybrid class Group public # # Returns `true` if the two groups use the same curve and have the same # parameters, `false` otherwise. # alias == eql? # # Returns the flags set on the group. # # See also #asn1_flag=. # def asn1_flag: () -> Integer # # Sets flags on the group. The flag value is used to determine how to encode the # group: encode explicit parameters or named curve using an OID. # # The flag value can be either of: # # * EC::NAMED_CURVE # * EC::EXPLICIT_CURVE # # # See the OpenSSL documentation for EC_GROUP_set_asn1_flag(). # def asn1_flag=: (Integer) -> Integer # # Returns the cofactor of the group. # # See the OpenSSL documentation for EC_GROUP_get_cofactor() # def cofactor: () -> BN # # Returns the curve name (sn). # # See the OpenSSL documentation for EC_GROUP_get_curve_name() # def curve_name: () -> String # # See the OpenSSL documentation for EC_GROUP_get_degree() # def degree: () -> Integer # # Returns `true` if the two groups use the same curve and have the same # parameters, `false` otherwise. # def eql?: (instance other) -> bool # # Returns the generator of the group. # # See the OpenSSL documentation for EC_GROUP_get0_generator() # def generator: () -> Point? # # Returns the order of the group. # # See the OpenSSL documentation for EC_GROUP_get_order() # def order: () -> BN # # Returns the form how EC::Point data is encoded as ASN.1. # # See also #point_conversion_form=. # def point_conversion_form: () -> point_conversion_format # # Sets the form how EC::Point data is encoded as ASN.1 as defined in X9.62. # # *format* can be one of these: # # `:compressed` # : Encoded as z||x, where z is an octet indicating which solution of the # equation y is. z will be 0x02 or 0x03. # `:uncompressed` # : Encoded as z||x||y, where z is an octet 0x04. # `:hybrid` # : Encodes as z||x||y, where z is an octet indicating which solution of the # equation y is. z will be 0x06 or 0x07. # # # See the OpenSSL documentation for EC_GROUP_set_point_conversion_form() # def point_conversion_form=: (point_conversion_format format) -> point_conversion_format # # See the OpenSSL documentation for EC_GROUP_get0_seed() # def seed: () -> String? # # See the OpenSSL documentation for EC_GROUP_set_seed() # def seed=: (String seed) -> String # # Sets the curve parameters. *generator* must be an instance of EC::Point that # is on the curve. *order* and *cofactor* are integers. # # See the OpenSSL documentation for EC_GROUP_set_generator() # def set_generator: (Point generator, Integer order, Integer cofactor) -> self # # See the OpenSSL documentation for i2d_ECPKParameters_bio() # def to_der: () -> String # # See the OpenSSL documentation for PEM_write_bio_ECPKParameters() # def to_pem: () -> String # # See the OpenSSL documentation for ECPKParameters_print() # def to_text: () -> String private # # Creates a new EC::Group object. # # If the first argument is :GFp or :GF2m, creates a new curve with given # parameters. # def initialize: (instance group) -> void | (String pem_or_der_encoded) -> void | (ec_method ec_method) -> void | (:GFp | :GF2m ec_method, Integer bignum_p, Integer bignum_a, Integer bignum_b) -> void # # def initialize_copy: (instance) -> void class Error < OpenSSL::OpenSSLError end end class Point public # # alias == eql? # # Performs elliptic curve point addition. # def add: (instance point) -> instance # # def eql?: (instance other) -> bool def group: () -> Group # # def infinity?: () -> bool # # def invert!: () -> self # # This method is deprecated and should not be used. This is a no-op. # def make_affine!: () -> self # # Performs elliptic curve point multiplication. # # The first form calculates `bn1 * point + bn2 * G`, where `G` is the generator # of the group of *point*. *bn2* may be omitted, and in that case, the result is # just `bn1 * point`. # # The second form calculates `bns[0] * point + bns[1] * points[0] + ... + # bns[-1] * points[-1] + bn2 * G`. *bn2* may be omitted. *bns* must be an array # of OpenSSL::BN. *points* must be an array of OpenSSL::PKey::EC::Point. Please # note that `points[0]` is not multiplied by `bns[0]`, but `bns[1]`. # def mul: (bn bn1, ?bn bn2) -> instance | (Array[bn] bns, Array[instance], ?bn bn2) -> instance # # def on_curve?: () -> bool # # def set_to_infinity!: () -> self # # Returns the octet string representation of the EC point as an instance of # OpenSSL::BN. # # If *conversion_form* is not given, the *point_conversion_form* attribute set # to the group is used. # # See #to_octet_string for more information. # def to_bn: (?point_conversion_format conversion_form) -> BN # # Returns the octet string representation of the elliptic curve point. # # *conversion_form* specifies how the point is converted. Possible values are: # # * `:compressed` # * `:uncompressed` # * `:hybrid` # def to_octet_string: (point_conversion_format) -> String private # # Creates a new instance of OpenSSL::PKey::EC::Point. If the only argument is an # instance of EC::Point, a copy is returned. Otherwise, creates a point that # belongs to *group*. # # *encoded_point* is the octet string representation of the point. This must be # either a String or an OpenSSL::BN. # def initialize: (instance point) -> void | (Group group, ?String | BN encoded_point) -> void # # def initialize_copy: (instance) -> void class Error < OpenSSL::OpenSSLError end end end class ECError < OpenSSL::PKey::PKeyError end # # An abstract class that bundles signature creation (PKey#sign) and validation # (PKey#verify) that is common to all implementations except OpenSSL::PKey::DH # * OpenSSL::PKey::RSA # * OpenSSL::PKey::DSA # * OpenSSL::PKey::EC # class PKey public # # Returns a string describing the PKey object. # def inspect: () -> String # # Returns the short name of the OID associated with *pkey*. # def oid: () -> String # # Serializes the private key to DER-encoded PKCS #8 format. If called without # arguments, unencrypted PKCS #8 PrivateKeyInfo format is used. If called with a # cipher name and a password, PKCS #8 EncryptedPrivateKeyInfo format with PBES2 # encryption scheme is used. # def private_to_der: (String cipher, String password) -> String | () -> String # # Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der # for more details. # def private_to_pem: (String cipher, String password) -> String | () -> String # # Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format. # def public_to_der: () -> String # # Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format. # def public_to_pem: () -> String # # Hashes and signs the `data` using a message digest algorithm `digest` and a # private key `pkey`. # # See #verify for the verification operation. # # See also the man page EVP_DigestSign(3). # # `digest` # : A String that represents the message digest algorithm name, or `nil` if # the PKey type requires no digest algorithm. For backwards compatibility, # this can be an instance of OpenSSL::Digest. Its state will not affect the # signature. # `data` # : A String. The data to be hashed and signed. # `options` # : A Hash that contains algorithm specific control operations to OpenSSL. See # OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details. `options` # parameter was added in version 3.0. # # # Example: # data = "Sign me!" # pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) # signopts = { rsa_padding_mode: "pss" } # signature = pkey.sign("SHA256", data, signopts) # # # Creates a copy of the RSA key pkey, but without the private components # pub_key = pkey.public_key # puts pub_key.verify("SHA256", signature, data, signopts) # => true # def sign: (Digest digest, String data) -> String # # Verifies the `signature` for the `data` using a message digest algorithm # `digest` and a public key `pkey`. # # Returns `true` if the signature is successfully verified, `false` otherwise. # The caller must check the return value. # # See #sign for the signing operation and an example. # # See also the man page EVP_DigestVerify(3). # # `digest` # : See #sign. # `signature` # : A String containing the signature to be verified. # `data` # : See #sign. # `options` # : See #sign. `options` parameter was added in version 3.0. # def verify: (Digest digest, String signature, String data) -> bool private # # Because PKey is an abstract class, actually calling this method explicitly # will raise a NotImplementedError. # def initialize: () -> void end # # Raised when errors occur during PKey#sign or PKey#verify. # class PKeyError < OpenSSL::OpenSSLError end # # RSA is an asymmetric public key algorithm that has been formalized in RFC # 3447. It is in widespread use in public key infrastructures (PKI) where # certificates (cf. OpenSSL::X509::Certificate) often are issued on the basis of # a public/private RSA key pair. RSA is used in a wide field of applications # such as secure (symmetric) key exchange, e.g. when establishing a secure # TLS/SSL connection. It is also used in various digital signature schemes. # class RSA < OpenSSL::PKey::PKey include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods # # Generates an RSA keypair. # # See also OpenSSL::PKey.generate_key. # # `size` # : The desired key size in bits. # `exponent` # : An odd Integer, normally 3, 17, or 65537. # def self.generate: (Integer size, ?Integer exponent) -> instance public def d: () -> BN? def dmp1: () -> BN? def dmq1: () -> BN? def e: () -> BN? # # Outputs this keypair in PEM encoding. If *cipher* and *pass_phrase* are given # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher # instance. # def export: (String cipher, String password) -> String | () -> String def iqmp: () -> BN? def n: () -> BN? def p: () -> BN? # # THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! # # Stores all parameters of key to the hash. The hash has keys 'n', 'e', 'd', # 'p', 'q', 'dmp1', 'dmq1', 'iqmp'. # # Don't use :-)) (It's up to you) # def params: () -> Hash[String, BN] # # Does this keypair contain a private key? # def private?: () -> bool # # Decrypt `string`, which has been encrypted with the public key, with the # private key. `padding` defaults to PKCS1_PADDING. # # **Deprecated in version 3.0**. Consider using PKey::PKey#encrypt and # PKey::PKey#decrypt instead. # def private_decrypt: (String data, ?Integer padding) -> String # # Encrypt `string` with the private key. `padding` defaults to PKCS1_PADDING. # The encrypted string output can be decrypted using #public_decrypt. # # **Deprecated in version 3.0**. Consider using PKey::PKey#sign_raw and # PKey::PKey#verify_raw, and PKey::PKey#verify_recover instead. # def private_encrypt: (String data, ?Integer padding) -> String # # The return value is always `true` since every private key is also a public # key. # def public?: () -> bool # # Decrypt `string`, which has been encrypted with the private key, with the # public key. `padding` defaults to PKCS1_PADDING. # # **Deprecated in version 3.0**. Consider using PKey::PKey#sign_raw and # PKey::PKey#verify_raw, and PKey::PKey#verify_recover instead. # def public_decrypt: (String data, ?Integer padding) -> String # # Encrypt `string` with the public key. `padding` defaults to PKCS1_PADDING. # The encrypted string output can be decrypted using #private_decrypt. # # **Deprecated in version 3.0**. Consider using PKey::PKey#encrypt and # PKey::PKey#decrypt instead. # def public_encrypt: (String data, ?Integer padding) -> String # # Returns a new RSA instance that carries just the public key components. # # This method is provided for backwards compatibility. In most cases, there is # no need to call this method. # # For the purpose of serializing the public key, to PEM or DER encoding of X.509 # SubjectPublicKeyInfo format, check PKey#public_to_pem and PKey#public_to_der. # def public_key: () -> instance def q: () -> BN? # # Sets *dmp1*, *dmq1*, *iqmp* for the RSA instance. They are calculated by `d # mod (p - 1)`, `d mod (q - 1)` and `q^(-1) mod p` respectively. # def set_crt_params: (bn dmp1, bn dmq1, bn iqmp) -> self # # Sets *p*, *q* for the RSA instance. # def set_factors: (bn p, bn q) -> self # # Sets *n*, *e*, *d* for the RSA instance. # def set_key: (bn n, bn e, bn d) -> self # # Signs *data* using the Probabilistic Signature Scheme (RSA-PSS) and returns # the calculated signature. # # RSAError will be raised if an error occurs. # # See #verify_pss for the verification operation. # # ### Parameters # *digest* # : A String containing the message digest algorithm name. # *data* # : A String. The data to be signed. # *salt_length* # : The length in octets of the salt. Two special values are reserved: # `:digest` means the digest length, and `:max` means the maximum possible # length for the combination of the private key and the selected message # digest algorithm. # *mgf1_hash* # : The hash algorithm used in MGF1 (the currently supported mask generation # function (MGF)). # # # ### Example # data = "Sign me!" # pkey = OpenSSL::PKey::RSA.new(2048) # signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256") # pub_key = OpenSSL::PKey.read(pkey.public_to_der) # puts pub_key.verify_pss("SHA256", signature, data, # salt_length: :auto, mgf1_hash: "SHA256") # => true # def sign_pss: (String digest, String data, salt_length: :digest | :max | Integer, mgf1_hash: String) -> String # # Outputs this keypair in DER encoding. # def to_der: () -> String # # Outputs this keypair in PEM encoding. If *cipher* and *pass_phrase* are given # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher # instance. # alias to_pem export # # Outputs this keypair in PEM encoding. If *cipher* and *pass_phrase* are given # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher # instance. # alias to_s export # # THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! # # Dumps all parameters of a keypair to a String # # Don't use :-)) (It's up to you) # def to_text: () -> String # # Verifies *data* using the Probabilistic Signature Scheme (RSA-PSS). # # The return value is `true` if the signature is valid, `false` otherwise. # RSAError will be raised if an error occurs. # # See #sign_pss for the signing operation and an example code. # # ### Parameters # *digest* # : A String containing the message digest algorithm name. # *data* # : A String. The data to be signed. # *salt_length* # : The length in octets of the salt. Two special values are reserved: # `:digest` means the digest length, and `:auto` means automatically # determining the length based on the signature. # *mgf1_hash* # : The hash algorithm used in MGF1. # def verify_pss: (String digest, String signature, String data, salt_length: :auto | :digest | Integer, mgf1_hash: String) -> bool private # # Generates or loads an RSA keypair. # # If called without arguments, creates a new instance with no key components # set. They can be set individually by #set_key, #set_factors, and # #set_crt_params. # # If called with a String, tries to parse as DER or PEM encoding of an RSA key. # Note that, if *passphrase* is not specified but the key is encrypted with a # passphrase, OpenSSL will prompt for it. See also OpenSSL::PKey.read which can # parse keys of any kinds. # # If called with a number, generates a new key pair. This form works as an alias # of RSA.generate. # # Examples: # OpenSSL::PKey::RSA.new 2048 # OpenSSL::PKey::RSA.new File.read 'rsa.pem' # OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase' # def initialize: () -> void | (Integer key_size) -> void | (String encoded_key, ?String pass_phrase) -> void # # def initialize_copy: (instance) -> void NO_PADDING: Integer PKCS1_OAEP_PADDING: Integer PKCS1_PADDING: Integer SSLV23_PADDING: Integer end # # Generic exception that is raised if an operation on an RSA PKey fails # unexpectedly or in case an instantiation of an instance of RSA fails due to # non-conformant input data. # class RSAError < OpenSSL::PKey::PKeyError end end module Random # # Reads bytes from *filename* and adds them to the PRNG. # def self.load_random_file: (String filename) -> true # # Mixes the bytes from *str* into the Pseudo Random Number Generator(PRNG) # state. # # Thus, if the data from *str* are unpredictable to an adversary, this increases # the uncertainty about the state and makes the PRNG output less predictable. # # The *entropy* argument is (the lower bound of) an estimate of how much # randomness is contained in *str*, measured in bytes. # # ### Example # # pid = $$ # now = Time.now # ary = [now.to_i, now.nsec, 1000, pid] # OpenSSL::Random.add(ary.join, 0.0) # OpenSSL::Random.seed(ary.join) # def self.random_add: (String str, Numeric entropy) -> self # # Generates a String with *length* number of cryptographically strong # pseudo-random bytes. # # ### Example # # OpenSSL::Random.random_bytes(12) # #=> "..." # def self.random_bytes: (Integer length) -> String # # ::seed is equivalent to ::add where *entropy* is length of *str*. # def self.seed: (String seed) -> String # # Return `true` if the PRNG has been seeded with enough data, `false` otherwise. # def self.status?: () -> bool # # Writes a number of random generated bytes (currently 1024) to *filename* which # can be used to initialize the PRNG by calling ::load_random_file in a later # session. # def self.write_random_file: (String filename) -> true class RandomError < OpenSSL::OpenSSLError end end # # Use SSLContext to set up the parameters for a TLS (former SSL) connection. # Both client and server TLS connections are supported, SSLSocket and SSLServer # may be used in conjunction with an instance of SSLContext to set up # connections. # module SSL # # def self.verify_certificate_identity: (X509::Certificate cert, String hostname) -> bool def self.verify_hostname: (String hostname, String san) -> bool def self.verify_wildcard: (String domain_component, String san_component) -> bool OP_ALL: Integer OP_ALLOW_NO_DHE_KEX: Integer OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: Integer OP_CIPHER_SERVER_PREFERENCE: Integer OP_CRYPTOPRO_TLSEXT_BUG: Integer OP_DONT_INSERT_EMPTY_FRAGMENTS: Integer # # Deprecated in OpenSSL 1.0.1k and 1.0.2. # OP_EPHEMERAL_RSA: Integer OP_LEGACY_SERVER_CONNECT: Integer # # Deprecated in OpenSSL 1.1.0. # OP_MICROSOFT_BIG_SSLV3_BUFFER: Integer # # Deprecated in OpenSSL 1.1.0. # OP_MICROSOFT_SESS_ID_BUG: Integer # # Deprecated in OpenSSL 0.9.7h and 0.9.8b. # OP_MSIE_SSLV2_RSA_PADDING: Integer # # Deprecated in OpenSSL 1.1.0. # OP_NETSCAPE_CA_DN_BUG: Integer # # Deprecated in OpenSSL 1.1.0. # OP_NETSCAPE_CHALLENGE_BUG: Integer # # Deprecated in OpenSSL 1.1.0. # OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: Integer # # Deprecated in OpenSSL 0.9.8q and 1.0.0c. # OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: Integer OP_NO_COMPRESSION: Integer OP_NO_ENCRYPT_THEN_MAC: Integer OP_NO_RENEGOTIATION: Integer OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: Integer # # Deprecated in OpenSSL 1.1.0. # OP_NO_SSLv2: Integer OP_NO_SSLv3: Integer OP_NO_TICKET: Integer OP_NO_TLSv1: Integer OP_NO_TLSv1_1: Integer OP_NO_TLSv1_2: Integer OP_NO_TLSv1_3: Integer # # Deprecated in OpenSSL 1.0.1. # OP_PKCS1_CHECK_1: Integer # # Deprecated in OpenSSL 1.0.1. # OP_PKCS1_CHECK_2: Integer OP_SAFARI_ECDHE_ECDSA_BUG: Integer # # Deprecated in OpenSSL 1.1.0. # OP_SINGLE_DH_USE: Integer # # Deprecated in OpenSSL 1.1.0. # OP_SINGLE_ECDH_USE: Integer # # Deprecated in OpenSSL 1.1.0. # OP_SSLEAY_080_CLIENT_DH_BUG: Integer # # Deprecated in OpenSSL 1.0.1h and 1.0.2. # OP_SSLREF2_REUSE_CERT_TYPE_BUG: Integer OP_TLSEXT_PADDING: Integer # # Deprecated in OpenSSL 1.1.0. # OP_TLS_BLOCK_PADDING_BUG: Integer # # Deprecated in OpenSSL 1.1.0. # OP_TLS_D5_BUG: Integer OP_TLS_ROLLBACK_BUG: Integer # # SSL 2.0 # SSL2_VERSION: Integer # # SSL 3.0 # SSL3_VERSION: Integer # # TLS 1.1 # TLS1_1_VERSION: Integer # # TLS 1.2 # TLS1_2_VERSION: Integer # # TLS 1.3 # TLS1_3_VERSION: Integer # # TLS 1.0 # TLS1_VERSION: Integer VERIFY_CLIENT_ONCE: Integer VERIFY_FAIL_IF_NO_PEER_CERT: Integer VERIFY_NONE: Integer VERIFY_PEER: Integer type tls_version = Symbol | Integer type verify_mode = Integer # # An SSLContext is used to set various options regarding certificates, # algorithms, verification, session caching, etc. The SSLContext is used to # create an SSLSocket. # # All attributes must be set before creating an SSLSocket as the SSLContext will # be frozen afterward. # class SSLContext public # # Adds a certificate to the context. *pkey* must be a corresponding private key # with *certificate*. # # Multiple certificates with different public key type can be added by repeated # calls of this method, and OpenSSL will choose the most appropriate certificate # during the handshake. # # #cert=, #key=, and #extra_chain_cert= are old accessor methods for setting # certificate and internally call this method. # # ### Parameters # *certificate* # : A certificate. An instance of OpenSSL::X509::Certificate. # *pkey* # : The private key for *certificate*. An instance of OpenSSL::PKey::PKey. # *extra_certs* # : Optional. An array of OpenSSL::X509::Certificate. When sending a # certificate chain, the certificates specified by this are sent following # *certificate*, in the order in the array. # # # ### Example # rsa_cert = OpenSSL::X509::Certificate.new(...) # rsa_pkey = OpenSSL::PKey.read(...) # ca_intermediate_cert = OpenSSL::X509::Certificate.new(...) # ctx.add_certificate(rsa_cert, rsa_pkey, [ca_intermediate_cert]) # # ecdsa_cert = ... # ecdsa_pkey = ... # another_ca_cert = ... # ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert]) # def add_certificate: (X509::Certificate certificate, PKey::PKey pkey, ?Array[X509::Certificate] extra_certs) -> self # # An Enumerable of Strings. Each String represents a protocol to be advertised # as the list of supported protocols for Application-Layer Protocol Negotiation. # Supported in OpenSSL 1.0.2 and higher. Has no effect on the server side. If # not set explicitly, the ALPN extension will not be included in the handshake. # # ### Example # # ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"] # def alpn_protocols: () -> Array[String]? # # An Enumerable of Strings. Each String represents a protocol to be advertised # as the list of supported protocols for Application-Layer Protocol Negotiation. # Supported in OpenSSL 1.0.2 and higher. Has no effect on the server side. If # not set explicitly, the ALPN extension will not be included in the handshake. # # ### Example # # ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"] # def alpn_protocols=: (Array[String]) -> Array[String] # # A callback invoked on the server side when the server needs to select a # protocol from the list sent by the client. Supported in OpenSSL 1.0.2 and # higher. The callback must return a protocol of those advertised by the client. # If none is acceptable, raising an error in the callback will cause the # handshake to fail. Not setting this callback explicitly means not supporting # the ALPN extension on the server - any protocols advertised by the client will # be ignored. # # ### Example # # ctx.alpn_select_cb = lambda do |protocols| # # inspect the protocols and select one # protocols.first # end # def alpn_select_cb: () -> (^(Array[String]) -> String? | nil) # # A callback invoked on the server side when the server needs to select a # protocol from the list sent by the client. Supported in OpenSSL 1.0.2 and # higher. The callback must return a protocol of those advertised by the client. # If none is acceptable, raising an error in the callback will cause the # handshake to fail. Not setting this callback explicitly means not supporting # the ALPN extension on the server - any protocols advertised by the client will # be ignored. # # ### Example # # ctx.alpn_select_cb = lambda do |protocols| # # inspect the protocols and select one # protocols.first # end # def alpn_select_cb=: (^(Array[String]) -> String? alpn_select_callback) -> void # # The path to a file containing a PEM-format CA certificate # def ca_file: () -> String # # The path to a file containing a PEM-format CA certificate # def ca_file=: (String ca_file) -> String # # The path to a directory containing CA certificates in PEM format. # # Files are looked up by subject's X509 name's hash value. # def ca_path: () -> String? # # The path to a directory containing CA certificates in PEM format. # # Files are looked up by subject's X509 name's hash value. # def ca_path=: (String ca_path) -> String # # Context certificate # # The *cert*, *key*, and *extra_chain_cert* attributes are deprecated. It is # recommended to use #add_certificate instead. # def cert: () -> X509::Certificate? # # Context certificate # # The *cert*, *key*, and *extra_chain_cert* attributes are deprecated. It is # recommended to use #add_certificate instead. # def cert=: (X509::Certificate cert) -> X509::Certificate # # An OpenSSL::X509::Store used for certificate verification. # def cert_store: () -> X509::Store? # # An OpenSSL::X509::Store used for certificate verification. # def cert_store=: (X509::Store store) -> X509::Store # # The list of cipher suites configured for this context. # def ciphers: () -> Array[[ String, String, Integer, Integer ]] # # Sets the list of available cipher suites for this context. Note in a server # context some ciphers require the appropriate certificates. For example, an # RSA cipher suite can only be chosen when an RSA certificate is available. # def ciphers=: (Array[[ String, String, Integer, Integer ]] ciphers) -> void | (Array[String] ciphers) -> void | (String colon_sep_ciphers) -> void # # A certificate or Array of certificates that will be sent to the client. # def client_ca: () -> (Array[X509::Certificate] | X509::Certificate) # # A certificate or Array of certificates that will be sent to the client. # def client_ca=: (Array[X509::Certificate] | X509::Certificate client_ca) -> void # # A callback invoked when a client certificate is requested by a server and no # certificate has been set. # # The callback is invoked with a Session and must return an Array containing an # OpenSSL::X509::Certificate and an OpenSSL::PKey. If any other value is # returned the handshake is suspended. # def client_cert_cb: () -> (^(Session) -> [ X509::Certificate, PKey::PKey ]? | nil) # # A callback invoked when a client certificate is requested by a server and no # certificate has been set. # # The callback is invoked with a Session and must return an Array containing an # OpenSSL::X509::Certificate and an OpenSSL::PKey. If any other value is # returned the handshake is suspended. # def client_cert_cb=: (^(Session) -> [ X509::Certificate, PKey::PKey ]? client_cert_cb) -> void # # Sets the list of "supported elliptic curves" for this context. # # For a TLS client, the list is directly used in the Supported Elliptic Curves # Extension. For a server, the list is used by OpenSSL to determine the set of # shared curves. OpenSSL will pick the most appropriate one from it. # # ### Example # ctx1 = OpenSSL::SSL::SSLContext.new # ctx1.ecdh_curves = "X25519:P-256:P-224" # svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1) # Thread.new { svr.accept } # # ctx2 = OpenSSL::SSL::SSLContext.new # ctx2.ecdh_curves = "P-256" # cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2) # cli.connect # # p cli.tmp_key.group.curve_name # # => "prime256v1" (is an alias for NIST P-256) # def ecdh_curves=: (String ecdh_curves) -> String # # Activate TLS_FALLBACK_SCSV for this context. See RFC 7507. # def enable_fallback_scsv: () -> nil # # An Array of extra X509 certificates to be added to the certificate chain. # # The *cert*, *key*, and *extra_chain_cert* attributes are deprecated. It is # recommended to use #add_certificate instead. # def extra_chain_cert: () -> Array[X509::Certificate]? # # An Array of extra X509 certificates to be added to the certificate chain. # # The *cert*, *key*, and *extra_chain_cert* attributes are deprecated. It is # recommended to use #add_certificate instead. # def extra_chain_cert=: (Array[X509::Certificate] extra_certs) -> Array[X509::Certificate] # # Removes sessions in the internal cache that have expired at *time*. # def flush_sessions: (Time time) -> self # # This method is called automatically when a new SSLSocket is created. However, # it is not thread-safe and must be called before creating SSLSocket objects in # a multi-threaded program. # alias freeze setup # # Context private key # # The *cert*, *key*, and *extra_chain_cert* attributes are deprecated. It is # recommended to use #add_certificate instead. # def key: () -> PKey::PKey? # # Context private key # # The *cert*, *key*, and *extra_chain_cert* attributes are deprecated. It is # recommended to use #add_certificate instead. # def key=: (PKey::PKey) -> PKey::PKey # # Sets the upper bound of the supported SSL/TLS protocol version. See # #min_version= for the possible values. # def max_version=: (tls_version version) -> tls_version # # Sets the lower bound on the supported SSL/TLS protocol version. The version # may be specified by an integer constant named OpenSSL::SSL::*_VERSION, a # Symbol, or `nil` which means "any version". # # Be careful that you don't overwrite OpenSSL::SSL::OP_NO_{SSL,TLS}v* options by # #options= once you have called #min_version= or #max_version=. # # ### Example # ctx = OpenSSL::SSL::SSLContext.new # ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION # # sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) # sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2 # def min_version=: (tls_version version) -> tls_version # # An Enumerable of Strings. Each String represents a protocol to be advertised # as the list of supported protocols for Next Protocol Negotiation. Supported in # OpenSSL 1.0.1 and higher. Has no effect on the client side. If not set # explicitly, the NPN extension will not be sent by the server in the handshake. # # ### Example # # ctx.npn_protocols = ["http/1.1", "spdy/2"] # def npn_protocols: () -> untyped # # An Enumerable of Strings. Each String represents a protocol to be advertised # as the list of supported protocols for Next Protocol Negotiation. Supported in # OpenSSL 1.0.1 and higher. Has no effect on the client side. If not set # explicitly, the NPN extension will not be sent by the server in the handshake. # # ### Example # # ctx.npn_protocols = ["http/1.1", "spdy/2"] # def npn_protocols=: (untyped) -> untyped # # A callback invoked on the client side when the client needs to select a # protocol from the list sent by the server. Supported in OpenSSL 1.0.1 and # higher. The client MUST select a protocol of those advertised by the server. # If none is acceptable, raising an error in the callback will cause the # handshake to fail. Not setting this callback explicitly means not supporting # the NPN extension on the client - any protocols advertised by the server will # be ignored. # # ### Example # # ctx.npn_select_cb = lambda do |protocols| # # inspect the protocols and select one # protocols.first # end # def npn_select_cb: () -> untyped # # A callback invoked on the client side when the client needs to select a # protocol from the list sent by the server. Supported in OpenSSL 1.0.1 and # higher. The client MUST select a protocol of those advertised by the server. # If none is acceptable, raising an error in the callback will cause the # handshake to fail. Not setting this callback explicitly means not supporting # the NPN extension on the client - any protocols advertised by the server will # be ignored. # # ### Example # # ctx.npn_select_cb = lambda do |protocols| # # inspect the protocols and select one # protocols.first # end # def npn_select_cb=: (untyped) -> untyped # # Gets various OpenSSL options. # def options: () -> Integer # # Sets various OpenSSL options. # def options=: (Integer ssl_options) -> Integer # # A callback invoked whenever a new handshake is initiated on an established # connection. May be used to disable renegotiation entirely. # # The callback is invoked with the active SSLSocket. The callback's return value # is ignored. A normal return indicates "approval" of the renegotiation and will # continue the process. To forbid renegotiation and to cancel the process, raise # an exception within the callback. # # ### Disable client renegotiation # # When running a server, it is often desirable to disable client renegotiation # entirely. You may use a callback as follows to implement this feature: # # ctx.renegotiation_cb = lambda do |ssl| # raise RuntimeError, "Client renegotiation disabled" # end # def renegotiation_cb: () -> (^(SSLSocket) -> void | nil) # # A callback invoked whenever a new handshake is initiated on an established # connection. May be used to disable renegotiation entirely. # # The callback is invoked with the active SSLSocket. The callback's return value # is ignored. A normal return indicates "approval" of the renegotiation and will # continue the process. To forbid renegotiation and to cancel the process, raise # an exception within the callback. # # ### Disable client renegotiation # # When running a server, it is often desirable to disable client renegotiation # entirely. You may use a callback as follows to implement this feature: # # ctx.renegotiation_cb = lambda do |ssl| # raise RuntimeError, "Client renegotiation disabled" # end # def renegotiation_cb=: (^(SSLSocket) -> void) -> void # # Returns the security level for the context. # # See also OpenSSL::SSL::SSLContext#security_level=. # def security_level: () -> Integer # # Sets the security level for the context. OpenSSL limits parameters according # to the level. The "parameters" include: ciphersuites, curves, key sizes, # certificate signature algorithms, protocol version and so on. For example, # level 1 rejects parameters offering below 80 bits of security, such as # ciphersuites using MD5 for the MAC or RSA keys shorter than 1024 bits. # # Note that attempts to set such parameters with insufficient security are also # blocked. You need to lower the level first. # # This feature is not supported in OpenSSL < 1.1.0, and setting the level to # other than 0 will raise NotImplementedError. Level 0 means everything is # permitted, the same behavior as previous versions of OpenSSL. # # See the manpage of SSL_CTX_set_security_level(3) for details. # def security_level=: (Integer sec_level) -> Integer # # A callback invoked at connect time to distinguish between multiple server # names. # # The callback is invoked with an SSLSocket and a server name. The callback # must return an SSLContext for the server name or nil. # def servername_cb: () -> (^(SSLSocket, String) -> SSLContext? | nil) # # A callback invoked at connect time to distinguish between multiple server # names. # # The callback is invoked with an SSLSocket and a server name. The callback # must return an SSLContext for the server name or nil. # def servername_cb=: (^(SSLSocket, String) -> SSLContext?) -> ^(SSLSocket, String) -> SSLContext? # # Adds *session* to the session cache. # def session_add: (Session) -> bool # # The current session cache mode. # def session_cache_mode: () -> Integer # # Sets the SSL session cache mode. Bitwise-or together the desired # SESSION_CACHE_* constants to set. See SSL_CTX_set_session_cache_mode(3) for # details. # def session_cache_mode=: (Integer) -> Integer # # Returns the current session cache size. Zero is used to represent an # unlimited cache size. # def session_cache_size: () -> Integer # # Sets the session cache size. Returns the previously valid session cache size. # Zero is used to represent an unlimited session cache size. # def session_cache_size=: (Integer) -> Integer # # Returns a Hash containing the following keys: # # :accept # : Number of started SSL/TLS handshakes in server mode # :accept_good # : Number of established SSL/TLS sessions in server mode # :accept_renegotiate # : Number of start renegotiations in server mode # :cache_full # : Number of sessions that were removed due to cache overflow # :cache_hits # : Number of successfully reused connections # :cache_misses # : Number of sessions proposed by clients that were not found in the cache # :cache_num # : Number of sessions in the internal session cache # :cb_hits # : Number of sessions retrieved from the external cache in server mode # :connect # : Number of started SSL/TLS handshakes in client mode # :connect_good # : Number of established SSL/TLS sessions in client mode # :connect_renegotiate # : Number of start renegotiations in client mode # :timeouts # : Number of sessions proposed by clients that were found in the cache but # had expired due to timeouts # def session_cache_stats: () -> Hash[Symbol, Integer] # # A callback invoked on a server when a session is proposed by the client but # the session could not be found in the server's internal cache. # # The callback is invoked with the SSLSocket and session id. The callback may # return a Session from an external cache. # def session_get_cb: () -> (^(SSLSocket, Integer) -> Session? | nil) # # A callback invoked on a server when a session is proposed by the client but # the session could not be found in the server's internal cache. # # The callback is invoked with the SSLSocket and session id. The callback may # return a Session from an external cache. # def session_get_cb=: (^(SSLSocket, Integer) -> Session?) -> void # # Sets the context in which a session can be reused. This allows sessions for # multiple applications to be distinguished, for example, by name. # def session_id_context: () -> Integer? # # Sets the context in which a session can be reused. This allows sessions for # multiple applications to be distinguished, for example, by name. # def session_id_context=: (Integer) -> Integer # # A callback invoked when a new session was negotiated. # # The callback is invoked with an SSLSocket. If `false` is returned the session # will be removed from the internal cache. # def session_new_cb: () -> (^(SSLSocket) -> untyped | nil) # # A callback invoked when a new session was negotiated. # # The callback is invoked with an SSLSocket. If `false` is returned the session # will be removed from the internal cache. # def session_new_cb=: (^(SSLSocket) -> untyped) -> ^(SSLSocket) -> untyped # # Removes *session* from the session cache. # def session_remove: (Session session) -> bool # # A callback invoked when a session is removed from the internal cache. # # The callback is invoked with an SSLContext and a Session. # # IMPORTANT NOTE: It is currently not possible to use this safely in a # multi-threaded application. The callback is called inside a global lock and it # can randomly cause deadlock on Ruby thread switching. # def session_remove_cb: () -> (^(SSLContext, Session) -> void | nil) # # A callback invoked when a session is removed from the internal cache. # # The callback is invoked with an SSLContext and a Session. # # IMPORTANT NOTE: It is currently not possible to use this safely in a # multi-threaded application. The callback is called inside a global lock and it # can randomly cause deadlock on Ruby thread switching. # def session_remove_cb=: (^(SSLContext, Session) -> void) -> void # # Sets saner defaults optimized for the use with HTTP-like protocols. # # If a Hash *params* is given, the parameters are overridden with it. The keys # in *params* must be assignment methods on SSLContext. # # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and cert_store are # not set then the system default certificate store is used. # def set_params: (?untyped params) -> untyped # # This method is called automatically when a new SSLSocket is created. However, # it is not thread-safe and must be called before creating SSLSocket objects in # a multi-threaded program. # def setup: () -> untyped # # Maximum session lifetime in seconds. # alias ssl_timeout timeout # # Maximum session lifetime in seconds. # alias ssl_timeout= timeout= # # Sets the SSL/TLS protocol version for the context. This forces connections to # use only the specified protocol version. This is deprecated and only provided # for backwards compatibility. Use #min_version= and #max_version= instead. # # ### History # As the name hints, this used to call the SSL_CTX_set_ssl_version() function # which sets the SSL method used for connections created from the context. As of # Ruby/OpenSSL 2.1, this accessor method is implemented to call #min_version= # and #max_version= instead. # def ssl_version=: (tls_version meth) -> tls_version # # Maximum session lifetime in seconds. # def timeout: () -> Integer? # # Maximum session lifetime in seconds. # def timeout=: (Integer) -> Integer # # A callback invoked when DH parameters are required for ephemeral DH key # exchange. # # The callback is invoked with the SSLSocket, a flag indicating the use of an # export cipher and the keylength required. # # The callback must return an OpenSSL::PKey::DH instance of the correct key # length. # # **Deprecated in version 3.0.** Use #tmp_dh= instead. # def tmp_dh_callback: () -> (^(Session, Integer, Integer) -> PKey::DH | nil) # # A callback invoked when DH parameters are required for ephemeral DH key # exchange. # # The callback is invoked with the SSLSocket, a flag indicating the use of an # export cipher and the keylength required. # # The callback must return an OpenSSL::PKey::DH instance of the correct key # length. # # **Deprecated in version 3.0.** Use #tmp_dh= instead. # def tmp_dh_callback=: (^(Session, Integer, Integer) -> PKey::DH) -> void # # A callback for additional certificate verification. The callback is invoked # for each certificate in the chain. # # The callback is invoked with two values. *preverify_ok* indicates indicates # if the verification was passed (`true`) or not (`false`). *store_context* is # an OpenSSL::X509::StoreContext containing the context used for certificate # verification. # # If the callback returns `false`, the chain verification is immediately stopped # and a bad_certificate alert is then sent. # def verify_callback: () -> (^(bool, X509::StoreContext) -> untyped | nil) # # A callback for additional certificate verification. The callback is invoked # for each certificate in the chain. # # The callback is invoked with two values. *preverify_ok* indicates indicates # if the verification was passed (`true`) or not (`false`). *store_context* is # an OpenSSL::X509::StoreContext containing the context used for certificate # verification. # # If the callback returns `false`, the chain verification is immediately stopped # and a bad_certificate alert is then sent. # def verify_callback=: (^(bool, X509::StoreContext) -> untyped) -> void # # Number of CA certificates to walk when verifying a certificate chain. # def verify_depth: () -> Integer? # # Number of CA certificates to walk when verifying a certificate chain. # def verify_depth=: (Integer) -> Integer # # Whether to check the server certificate is valid for the hostname. # # In order to make this work, verify_mode must be set to VERIFY_PEER and the # server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=. # def verify_hostname: () -> bool? # # Whether to check the server certificate is valid for the hostname. # # In order to make this work, verify_mode must be set to VERIFY_PEER and the # server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=. # def verify_hostname=: [U] (boolish) -> U # # Session verification mode. # # Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE, # VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL # # The default mode is VERIFY_NONE, which does not perform any verification at # all. # # See SSL_CTX_set_verify(3) for details. # def verify_mode: () -> verify_mode? # # Session verification mode. # # Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE, # VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL # # The default mode is VERIFY_NONE, which does not perform any verification at # all. # # See SSL_CTX_set_verify(3) for details. # def verify_mode=: (verify_mode) -> verify_mode private # # Creates a new SSL context. # # If an argument is given, #ssl_version= is called with the value. Note that # this form is deprecated. New applications should use #min_version= and # #max_version= as necessary. # def initialize: (?tls_version version) -> void # # Sets the minimum and maximum supported protocol versions. See #min_version= # and #max_version=. # def set_minmax_proto_version: (untyped, untyped) -> untyped DEFAULT_CERT_STORE: X509::Store DEFAULT_PARAMS: Hash[Symbol, untyped] DEFAULT_TMP_DH_CALLBACK: Proc # # The list of available SSL/TLS methods. This constant is only provided for # backwards compatibility. # METHODS: Array[Symbol] # # Both client and server sessions are added to the session cache # SESSION_CACHE_BOTH: Integer # # Client sessions are added to the session cache # SESSION_CACHE_CLIENT: Integer # # Normally the session cache is checked for expired sessions every 255 # connections. Since this may lead to a delay that cannot be controlled, the # automatic flushing may be disabled and #flush_sessions can be called # explicitly. # SESSION_CACHE_NO_AUTO_CLEAR: Integer # # Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and # SESSION_CACHE_NO_INTERNAL_STORE. # SESSION_CACHE_NO_INTERNAL: Integer # # Always perform external lookups of sessions even if they are in the internal # cache. # # This flag has no effect on clients # SESSION_CACHE_NO_INTERNAL_LOOKUP: Integer # # Never automatically store sessions in the internal store. # SESSION_CACHE_NO_INTERNAL_STORE: Integer # # No session caching for client or server # SESSION_CACHE_OFF: Integer # # Server sessions are added to the session cache # SESSION_CACHE_SERVER: Integer end # # Generic error class raised by SSLSocket and SSLContext. # class SSLError < OpenSSL::OpenSSLError end class SSLErrorWaitReadable < OpenSSL::SSL::SSLError include IO::WaitReadable end class SSLErrorWaitWritable < OpenSSL::SSL::SSLError include IO::WaitWritable end # # SSLServer represents a TCP/IP server socket with Secure Sockets Layer. # class SSLServer include OpenSSL::SSL::SocketForwarder public # # Works similar to TCPServer#accept. # def accept: () -> SSLSocket # # See IO#close for details. # def close: () -> nil # # See TCPServer#listen for details. # def listen: (Integer backlog) -> void # # See BasicSocket#shutdown for details. # def shutdown: (Symbol | String | Integer how) -> void # # When true then #accept works exactly the same as TCPServer#accept # def start_immediately: () -> bool # # When true then #accept works exactly the same as TCPServer#accept # def start_immediately=: [U] (boolish) -> U # # Returns the TCPServer passed to the SSLServer when initialized. # def to_io: () -> (TCPServer | UNIXServer) private # # Creates a new instance of SSLServer. # * *srv* is an instance of TCPServer. # * *ctx* is an instance of OpenSSL::SSL::SSLContext. # def initialize: (TCPServer | UNIXServer svr, untyped ctx) -> void end class SSLSocket include OpenSSL::SSL::SocketForwarder include OpenSSL::Buffering # # Creates a new instance of SSLSocket. *remote*host_ and *remote*port_ are used # to open TCPSocket. If *local*host_ and *local*port_ are specified, then those # parameters are used on the local end to establish the connection. If *context* # is provided, the SSL Sockets initial params will be taken from the context. # # ### Examples # # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443) # sock.connect # Initiates a connection to localhost:443 # # with SSLContext: # # ctx = OpenSSL::SSL::SSLContext.new # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443, context: ctx) # sock.connect # Initiates a connection to localhost:443 with SSLContext # def self.open: (untyped remote_host, untyped remote_port, ?untyped local_host, ?untyped local_port, ?context: untyped) -> untyped public # # Waits for a SSL/TLS client to initiate a handshake. # def accept: () -> self # # Initiates the SSL/TLS handshake as a server in non-blocking manner. # # # emulates blocking accept # begin # ssl.accept_nonblock # rescue IO::WaitReadable # IO.select([s2]) # retry # rescue IO::WaitWritable # IO.select(nil, [s2]) # retry # end # # By specifying a keyword argument *exception* to `false`, you can indicate that # accept_nonblock should not raise an IO::WaitReadable or IO::WaitWritable # exception, but return the symbol `:wait_readable` or `:wait_writable` instead. # def accept_nonblock: (?exception: true) -> self | (exception: false) -> (self | :wait_readable | :wait_writable) # # Returns the ALPN protocol string that was finally selected by the server # during the handshake. # def alpn_protocol: () -> String? # # The X509 certificate for this socket endpoint. # def cert: () -> X509::Certificate? # # Returns the cipher suite actually used in the current session, or nil if no # session has been established. # def cipher: () -> [ String, String, Integer, Integer ]? # # Returns the list of client CAs. Please note that in contrast to # SSLContext#client_ca= no array of X509::Certificate is returned but X509::Name # instances of the CA's subject distinguished name. # # In server mode, returns the list set by SSLContext#client_ca=. In client mode, # returns the list of client CAs sent from the server. # def client_ca: () -> (Array[X509::Name] | Array[X509::Certificate] | X509::Certificate) # # Initiates an SSL/TLS handshake with a server. # def connect: () -> self # # Initiates the SSL/TLS handshake as a client in non-blocking manner. # # # emulates blocking connect # begin # ssl.connect_nonblock # rescue IO::WaitReadable # IO.select([s2]) # retry # rescue IO::WaitWritable # IO.select(nil, [s2]) # retry # end # # By specifying a keyword argument *exception* to `false`, you can indicate that # connect_nonblock should not raise an IO::WaitReadable or IO::WaitWritable # exception, but return the symbol `:wait_readable` or `:wait_writable` instead. # def connect_nonblock: (?exception: true) -> self | (exception: false) -> (self | :wait_readable | :wait_writable) # # The SSLContext object used in this connection. # def context: () -> SSLContext # # Returns the last **Finished** message sent # def finished_message: () -> String? def hostname: () -> String? # # Sets the server hostname used for SNI. This needs to be set before # SSLSocket#connect. # def hostname=: (String) -> String # # The underlying IO object. # def io: () -> BasicSocket # # Returns the protocol string that was finally selected by the client during the # handshake. # def npn_protocol: () -> String? # # The X509 certificate for this socket's peer. # def peer_cert: () -> X509::Certificate? # # The X509 certificate chain for this socket's peer. # def peer_cert_chain: () -> Array[X509::Certificate]? # # Returns the last **Finished** message received # def peer_finished_message: () -> String? # # The number of bytes that are immediately available for reading. # def pending: () -> Integer # # Perform hostname verification following RFC 6125. # # This method MUST be called after calling #connect to ensure that the hostname # of a remote peer has been verified. # def post_connection_check: (String hostname) -> true # # Returns the SSLSession object currently used, or nil if the session is not # established. # def session: () -> Session? # # Sets the Session to be used when the connection is established. # def session=: (Session) -> Session # # Returns `true` if a reused session was negotiated during the handshake. # def session_reused?: () -> bool # # Returns a String representing the SSL/TLS version that was negotiated for the # connection, for example "TLSv1.2". # def ssl_version: () -> tls_version # # A description of the current connection state. This is for diagnostic purposes # only. # def state: () -> String # # Whether to close the underlying socket as well, when the SSL/TLS connection is # shut down. This defaults to `false`. # def sync_close: () -> bool # # Whether to close the underlying socket as well, when the SSL/TLS connection is # shut down. This defaults to `false`. # def sync_close=: [U] (boolish) -> U # # Sends "close notify" to the peer and tries to shut down the SSL connection # gracefully. # # If sync_close is set to `true`, the underlying IO is also closed. # def sysclose: () -> nil # # Reads *length* bytes from the SSL connection. If a pre-allocated *buffer* is # provided the data will be written into it. # def sysread: (Integer length, ?String buffer) -> String # # Writes *string* to the SSL connection. # def syswrite: (String data) -> Integer # # Returns the ephemeral key used in case of forward secrecy cipher. # def tmp_key: () -> PKey::PKey? # # The underlying IO object. # alias to_io io # # Returns the result of the peer certificates verification. See verify(1) for # error values and descriptions. # # If no peer certificate was presented X509_V_OK is returned. # def verify_result: () -> Integer private # # def client_cert_cb: () -> untyped # # Creates a new SSL socket from *io* which must be a real IO object (not an # IO-like object that responds to read/write). # # If *ctx* is provided the SSL Sockets initial params will be taken from the # context. # # The OpenSSL::Buffering module provides additional IO methods. # # This method will freeze the SSLContext if one is provided; however, session # management is still allowed in the frozen SSLContext. # def initialize: (*untyped) -> void # # def session_get_cb: () -> untyped # # def session_new_cb: () -> untyped # # Sends "close notify" to the peer and tries to shut down the SSL connection # gracefully. # def stop: () -> untyped # # A non-blocking version of #sysread. Raises an SSLError if reading would # block. If "exception: false" is passed, this method returns a symbol of # :wait_readable, :wait_writable, or nil, rather than raising an exception. # # Reads *length* bytes from the SSL connection. If a pre-allocated *buffer* is # provided the data will be written into it. # def sysread_nonblock: (*untyped) -> untyped # # Writes *string* to the SSL connection in a non-blocking manner. Raises an # SSLError if writing would block. # def syswrite_nonblock: (*untyped) -> untyped # # def tmp_dh_callback: () -> untyped # # def tmp_ecdh_callback: () -> untyped # # def using_anon_cipher?: () -> untyped end class Session public # # Returns `true` if the two Session is the same, `false` if not. # def ==: (instance other) -> bool # # Returns the Session ID. # def id: () -> String # # Returns the time at which the session was established. # def time: () -> Time # # Sets start time of the session. Time resolution is in seconds. # def time=: (Time | Integer start_time) -> Time # # Returns the timeout value set for the session, in seconds from the established # time. # def timeout: () -> Integer # # Sets how long until the session expires in seconds. # def timeout=: (Integer timeout) -> Integer # # Returns an ASN1 encoded String that contains the Session object. # def to_der: () -> String # # Returns a PEM encoded String that contains the Session object. # def to_pem: () -> String # # Shows everything in the Session object. This is for diagnostic purposes. # def to_text: () -> String private # # Creates a new Session object from an instance of SSLSocket or DER/PEM encoded # String. # def initialize: (SSLSocket | String sock_or_str) -> void # # def initialize_copy: (instance) -> void class SessionError < OpenSSL::OpenSSLError end end module SocketForwarder public # # def addr: () -> Addrinfo? # # def closed?: () -> untyped # # def do_not_reverse_lookup=: (boolish flag) -> boolish # # def fcntl: (*untyped args) -> untyped # # The file descriptor for the socket. # def fileno: () -> Integer # # def getsockopt: (Symbol | Integer level, Symbol | Integer optname) -> (Integer | boolish | String) # # def peeraddr: () -> untyped # # def setsockopt: (untyped level, untyped optname, untyped optval) -> untyped end end # # Provides classes and methods to request, create and validate # [RFC3161-compliant](http://www.ietf.org/rfc/rfc3161.txt) timestamps. Request # may be used to either create requests from scratch or to parse existing # requests that again can be used to request timestamps from a timestamp server, # e.g. via the net/http. The resulting timestamp response may be parsed using # Response. # # Please note that Response is read-only and immutable. To create a Response, an # instance of Factory as well as a valid Request are needed. # # ### Create a Response: # #Assumes ts.p12 is a PKCS#12-compatible file with a private key # #and a certificate that has an extended key usage of 'timeStamping' # p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd') # md = OpenSSL::Digest.new('SHA1') # hash = md.digest(data) #some binary data to be timestamped # req = OpenSSL::Timestamp::Request.new # req.algorithm = 'SHA1' # req.message_imprint = hash # req.policy_id = "1.2.3.4.5" # req.nonce = 42 # fac = OpenSSL::Timestamp::Factory.new # fac.gen_time = Time.now # fac.serial_number = 1 # timestamp = fac.create_timestamp(p12.key, p12.certificate, req) # # ### Verify a timestamp response: # #Assume we have a timestamp token in a file called ts.der # ts = OpenSSL::Timestamp::Response.new(File.binread('ts.der')) # #Assume we have the Request for this token in a file called req.der # req = OpenSSL::Timestamp::Request.new(File.binread('req.der')) # # Assume the associated root CA certificate is contained in a # # DER-encoded file named root.cer # root = OpenSSL::X509::Certificate.new(File.binread('root.cer')) # # get the necessary intermediate certificates, available in # # DER-encoded form in inter1.cer and inter2.cer # inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer')) # inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer')) # ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails # module Timestamp # # Used to generate a Response from scratch. # # Please bear in mind that the implementation will always apply and prefer the # policy object identifier given in the request over the default policy id # specified in the Factory. As a consequence, `default_policy_id` will only be # applied if no Request#policy_id was given. But this also means that one needs # to check the policy identifier in the request manually before creating the # Response, e.g. to check whether it complies to a specific set of acceptable # policies. # # There exists also the possibility to add certificates (instances of # OpenSSL::X509::Certificate) besides the timestamping certificate that will be # included in the resulting timestamp token if Request#cert_requested? is # `true`. Ideally, one would also include any intermediate certificates (the # root certificate can be left out - in order to trust it any verifying party # will have to be in its possession anyway). This simplifies validation of the # timestamp since these intermediate certificates are "already there" and need # not be passed as external parameters to Response#verify anymore, thus # minimizing external resources needed for verification. # # ### Example: Inclusion of (untrusted) intermediate certificates # # Assume we received a timestamp request that has set Request#policy_id to `nil` # and Request#cert_requested? to true. The raw request bytes are stored in a # variable called `req_raw`. We'd still like to integrate the necessary # intermediate certificates (in `inter1.cer` and `inter2.cer`) to simplify # validation of the resulting Response. `ts.p12` is a PKCS#12-compatible file # including the private key and the timestamping certificate. # # req = OpenSSL::Timestamp::Request.new(raw_bytes) # p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd') # inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer')) # inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer')) # fac = OpenSSL::Timestamp::Factory.new # fac.gen_time = Time.now # fac.serial_number = 1 # fac.allowed_digests = ["sha256", "sha384", "sha512"] # #needed because the Request contained no policy identifier # fac.default_policy_id = '1.2.3.4.5' # fac.additional_certificates = [ inter1, inter2 ] # timestamp = fac.create_timestamp(p12.key, p12.certificate, req) # # ## Attributes # # ### default_policy_id # # Request#policy_id will always be preferred over this if present in the # Request, only if Request#policy_id is nil default_policy will be used. If none # of both is present, a TimestampError will be raised when trying to create a # Response. # # call-seq: # factory.default_policy_id = "string" -> string # factory.default_policy_id -> string or nil # # ### serial_number # # Sets or retrieves the serial number to be used for timestamp creation. Must be # present for timestamp creation. # # call-seq: # factory.serial_number = number -> number # factory.serial_number -> number or nil # # ### gen_time # # Sets or retrieves the Time value to be used in the Response. Must be present # for timestamp creation. # # call-seq: # factory.gen_time = Time -> Time # factory.gen_time -> Time or nil # # ### additional_certs # # Sets or retrieves additional certificates apart from the timestamp certificate # (e.g. intermediate certificates) to be added to the Response. Must be an Array # of OpenSSL::X509::Certificate. # # call-seq: # factory.additional_certs = [cert1, cert2] -> [ cert1, cert2 ] # factory.additional_certs -> array or nil # # ### allowed_digests # # Sets or retrieves the digest algorithms that the factory is allowed create # timestamps for. Known vulnerable or weak algorithms should not be allowed # where possible. Must be an Array of String or OpenSSL::Digest subclass # instances. # # call-seq: # factory.allowed_digests = ["sha1", OpenSSL::Digest.new('SHA256').new] -> [ "sha1", OpenSSL::Digest) ] # factory.allowed_digests -> array or nil # class Factory public def additional_certs: () -> Array[X509::Certificate]? def additional_certs=: (Array[X509::Certificate]? certs) -> Array[X509::Certificate]? def allowed_digests: () -> Array[String | Digest]? def allowed_digests=: (Array[String | Digest]) -> Array[String | Digest] # # Creates a Response with the help of an OpenSSL::PKey, an # OpenSSL::X509::Certificate and a Request. # # Mandatory parameters for timestamp creation that need to be set in the # Request: # # * Request#algorithm # * Request#message_imprint # # # Mandatory parameters that need to be set in the Factory: # * Factory#serial_number # * Factory#gen_time # * Factory#allowed_digests # # # In addition one of either Request#policy_id or Factory#default_policy_id must # be set. # # Raises a TimestampError if creation fails, though successfully created error # responses may be returned. # def create_timestamp: (PKey::PKey key, X509::Certificate cert, Request request) -> Response def default_policy_id: () -> String? def default_policy_id=: (String) -> String def gen_time: () -> Time? def gen_time=: (Time) -> Time def serial_number: () -> Integer? def serial_number=: (Integer) -> Integer end # # Allows to create timestamp requests or parse existing ones. A Request is also # needed for creating timestamps from scratch with Factory. When created from # scratch, some default values are set: # * version is set to `1` # * cert_requested is set to `true` # * algorithm, message_imprint, policy_id, and nonce are set to `false` # class Request public # # Returns the 'short name' of the object identifier that represents the # algorithm that was used to create the message imprint digest. # def algorithm: () -> String # # Allows to set the object identifier or the 'short name' of the algorithm that # was used to create the message imprint digest. # # ### Example: # request.algorithm = "SHA1" # def algorithm=: (String) -> String # # Specify whether the response shall contain the timestamp authority's # certificate or not. The default value is `true`. # def cert_requested=: [U] (boolish) -> U # # Indicates whether the response shall contain the timestamp authority's # certificate or not. # def cert_requested?: () -> bool # # Returns the message imprint (digest) of the data to be timestamped. # def message_imprint: () -> String? # # Set the message imprint digest. # def message_imprint=: (String) -> String # # Returns the nonce (number used once) that the server shall include in its # response. # def nonce: () -> BN? # # Sets the nonce (number used once) that the server shall include in its # response. If the nonce is set, the server must return the same nonce value in # a valid Response. # def nonce=: (bn nonce) -> BN # # Returns the 'short name' of the object identifier that represents the # timestamp policy under which the server shall create the timestamp. # def policy_id: () -> String? # # Allows to set the object identifier that represents the timestamp policy under # which the server shall create the timestamp. This may be left `nil`, implying # that the timestamp server will issue the timestamp using some default policy. # # ### Example: # request.policy_id = "1.2.3.4.5" # def policy_id=: (String policy_id) -> String # # DER-encodes this Request. # def to_der: () -> String # # Returns the version of this request. `1` is the default value. # def version: () -> Integer # # Sets the version number for this Request. This should be `1` for compliant # servers. # def version=: (Integer) -> Integer private # # When creating a Request with the `File` or `string` parameter, the # corresponding `File` or `string` must be DER-encoded. # def initialize: (?File | String request_der) -> void end # # Immutable and read-only representation of a timestamp response returned from a # timestamp server after receiving an associated Request. Allows access to # specific information about the response but also allows to verify the # Response. # class Response public # # In cases no timestamp token has been created, this field contains further info # about the reason why response creation failed. The method returns either nil # (the request was successful and a timestamp token was created) or one of the # following: # * :BAD_ALG - Indicates that the timestamp server rejects the message imprint # algorithm used in the Request # * :BAD_REQUEST - Indicates that the timestamp server was not able to process # the Request properly # * :BAD_DATA_FORMAT - Indicates that the timestamp server was not able to # parse certain data in the Request # * :TIME_NOT_AVAILABLE - Indicates that the server could not access its time # source # * :UNACCEPTED_POLICY - Indicates that the requested policy identifier is not # recognized or supported by the timestamp server # * :UNACCEPTED_EXTENSIION - Indicates that an extension in the Request is not # supported by the timestamp server # * :ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested # is either not understood or currently not available # * :SYSTEM_FAILURE - Timestamp creation failed due to an internal error that # occurred on the timestamp server # def failure_info: () -> Symbol? # # Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING, # REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has been # created only in case `status` is equal to GRANTED or GRANTED_WITH_MODS. # def status: () -> BN # # In cases of failure this field may contain an array of strings further # describing the origin of the failure. # def status_text: () -> Array[String]? # # Returns the Response in DER-encoded form. # def to_der: () -> String # # If a timestamp token is present, this returns it in the form of a # OpenSSL::PKCS7. # def token: () -> PKCS7? # # Get the response's token info if present. # def token_info: () -> TokenInfo? # # If the Request specified to request the TSA certificate # (Request#cert_requested = true), then this field contains the certificate of # the timestamp authority. # def tsa_certificate: () -> X509::Certificate? # # Verifies a timestamp token by checking the signature, validating the # certificate chain implied by tsa_certificate and by checking conformance to a # given Request. Mandatory parameters are the Request associated to this # Response, and an OpenSSL::X509::Store of trusted roots. # # Intermediate certificates can optionally be supplied for creating the # certificate chain. These intermediate certificates must all be instances of # OpenSSL::X509::Certificate. # # If validation fails, several kinds of exceptions can be raised: # * TypeError if types don't fit # * TimestampError if something is wrong with the timestamp token itself, if # it is not conformant to the Request, or if validation of the timestamp # certificate chain fails. # def verify: (Request request, X509::Store store, ?X509::Certificate intermediate_cert) -> instance private # # Creates a Response from a `File` or `string` parameter, the corresponding # `File` or `string` must be DER-encoded. Please note that Response is an # immutable read-only class. If you'd like to create timestamps please refer to # Factory instead. # def initialize: (File | String response_der) -> void # # Indicates a successful response. Equal to `0`. # GRANTED: Integer # # Indicates a successful response that probably contains modifications from the # initial request. Equal to `1`. # GRANTED_WITH_MODS: Integer # # Indicates a failure. No timestamp token was created. Equal to `2`. # REJECTION: Integer # # Indicates a failure. No timestamp token was created. A certificate has been # revoked. Equal to `5`. # REVOCATION_NOTIFICATION: Integer # # Indicates a failure. No timestamp token was created. Revocation of a # certificate is imminent. Equal to `4`. # REVOCATION_WARNING: Integer # # Indicates a failure. No timestamp token was created. Equal to `3`. # WAITING: Integer end # # Generic exception class of the Timestamp module. # class TimestampError < OpenSSL::OpenSSLError end # # Immutable and read-only representation of a timestamp token info from a # Response. # class TokenInfo public # # Returns the 'short name' of the object identifier representing the algorithm # that was used to derive the message imprint digest. For valid timestamps, this # is the same value that was already given in the Request. If status is GRANTED # or GRANTED_WITH_MODS, this is never `nil`. # # ### Example: # algo = token_info.algorithm # puts algo -> "SHA1" # def algorithm: () -> String? # # Returns time when this timestamp token was created. If status is GRANTED or # GRANTED_WITH_MODS, this is never `nil`. # def gen_time: () -> Time # # Returns the message imprint digest. For valid timestamps, this is the same # value that was already given in the Request. If status is GRANTED or # GRANTED_WITH_MODS, this is never `nil`. # # ### Example: # mi = token_info.msg_imprint # puts mi -> "DEADBEEF" # def message_imprint: () -> String # # If the timestamp token is valid then this field contains the same nonce that # was passed to the timestamp server in the initial Request. # def nonce: () -> BN? # # If the ordering field is missing, or if the ordering field is present and set # to false, then the genTime field only indicates the time at which the # time-stamp token has been created by the TSA. In such a case, the ordering of # time-stamp tokens issued by the same TSA or different TSAs is only possible # when the difference between the genTime of the first time-stamp token and the # genTime of the second time-stamp token is greater than the sum of the # accuracies of the genTime for each time-stamp token. # # If the ordering field is present and set to true, every time-stamp token from # the same TSA can always be ordered based on the genTime field, regardless of # the genTime accuracy. # def ordering: () -> bool? # # Returns the timestamp policy object identifier of the policy this timestamp # was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never # `nil`. # # ### Example: # id = token_info.policy_id # puts id -> "1.2.3.4.5" # def policy_id: () -> String? # # Returns serial number of the timestamp token. This value shall never be the # same for two timestamp tokens issued by a dedicated timestamp authority. If # status is GRANTED or GRANTED_WITH_MODS, this is never `nil`. # def serial_number: () -> BN? # # Returns the TokenInfo in DER-encoded form. # def to_der: () -> String # # Returns the version number of the token info. With compliant servers, this # value should be `1` if present. If status is GRANTED or GRANTED_WITH_MODS. # def version: () -> Integer private # # Creates a TokenInfo from a `File` or `string` parameter, the corresponding # `File` or `string` must be DER-encoded. Please note that TokenInfo is an # immutable read-only class. If you'd like to create timestamps please refer to # Factory instead. # def initialize: (File | String token_der) -> void end end module X509 DEFAULT_CERT_AREA: String DEFAULT_CERT_DIR: String DEFAULT_CERT_DIR_ENV: String DEFAULT_CERT_FILE: String DEFAULT_CERT_FILE_ENV: String DEFAULT_PRIVATE_DIR: String PURPOSE_ANY: Integer PURPOSE_CRL_SIGN: Integer PURPOSE_NS_SSL_SERVER: Integer PURPOSE_OCSP_HELPER: Integer PURPOSE_SMIME_ENCRYPT: Integer PURPOSE_SMIME_SIGN: Integer PURPOSE_SSL_CLIENT: Integer PURPOSE_SSL_SERVER: Integer PURPOSE_TIMESTAMP_SIGN: Integer TRUST_COMPAT: Integer TRUST_EMAIL: Integer TRUST_OBJECT_SIGN: Integer TRUST_OCSP_REQUEST: Integer TRUST_OCSP_SIGN: Integer TRUST_SSL_CLIENT: Integer TRUST_SSL_SERVER: Integer TRUST_TSA: Integer V_ERR_AKID_ISSUER_SERIAL_MISMATCH: Integer V_ERR_AKID_SKID_MISMATCH: Integer V_ERR_APPLICATION_VERIFICATION: Integer V_ERR_CA_KEY_TOO_SMALL: Integer V_ERR_CA_MD_TOO_WEAK: Integer V_ERR_CERT_CHAIN_TOO_LONG: Integer V_ERR_CERT_HAS_EXPIRED: Integer V_ERR_CERT_NOT_YET_VALID: Integer V_ERR_CERT_REJECTED: Integer V_ERR_CERT_REVOKED: Integer V_ERR_CERT_SIGNATURE_FAILURE: Integer V_ERR_CERT_UNTRUSTED: Integer V_ERR_CRL_HAS_EXPIRED: Integer V_ERR_CRL_NOT_YET_VALID: Integer V_ERR_CRL_PATH_VALIDATION_ERROR: Integer V_ERR_CRL_SIGNATURE_FAILURE: Integer V_ERR_DANE_NO_MATCH: Integer V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: Integer V_ERR_DIFFERENT_CRL_SCOPE: Integer V_ERR_EE_KEY_TOO_SMALL: Integer V_ERR_EMAIL_MISMATCH: Integer V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: Integer V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: Integer V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: Integer V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: Integer V_ERR_EXCLUDED_VIOLATION: Integer V_ERR_HOSTNAME_MISMATCH: Integer V_ERR_INVALID_CA: Integer V_ERR_INVALID_CALL: Integer V_ERR_INVALID_EXTENSION: Integer V_ERR_INVALID_NON_CA: Integer V_ERR_INVALID_POLICY_EXTENSION: Integer V_ERR_INVALID_PURPOSE: Integer V_ERR_IP_ADDRESS_MISMATCH: Integer V_ERR_KEYUSAGE_NO_CERTSIGN: Integer V_ERR_KEYUSAGE_NO_CRL_SIGN: Integer V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: Integer V_ERR_NO_EXPLICIT_POLICY: Integer V_ERR_NO_VALID_SCTS: Integer V_ERR_OCSP_CERT_UNKNOWN: Integer V_ERR_OCSP_VERIFY_FAILED: Integer V_ERR_OCSP_VERIFY_NEEDED: Integer V_ERR_OUT_OF_MEM: Integer V_ERR_PATH_LENGTH_EXCEEDED: Integer V_ERR_PATH_LOOP: Integer V_ERR_PERMITTED_VIOLATION: Integer V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: Integer V_ERR_PROXY_PATH_LENGTH_EXCEEDED: Integer V_ERR_PROXY_SUBJECT_NAME_VIOLATION: Integer V_ERR_SELF_SIGNED_CERT_IN_CHAIN: Integer V_ERR_STORE_LOOKUP: Integer V_ERR_SUBJECT_ISSUER_MISMATCH: Integer V_ERR_SUBTREE_MINMAX: Integer V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: Integer V_ERR_SUITE_B_INVALID_ALGORITHM: Integer V_ERR_SUITE_B_INVALID_CURVE: Integer V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: Integer V_ERR_SUITE_B_INVALID_VERSION: Integer V_ERR_SUITE_B_LOS_NOT_ALLOWED: Integer V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: Integer V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: Integer V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: Integer V_ERR_UNABLE_TO_GET_CRL: Integer V_ERR_UNABLE_TO_GET_CRL_ISSUER: Integer V_ERR_UNABLE_TO_GET_ISSUER_CERT: Integer V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: Integer V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: Integer V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: Integer V_ERR_UNHANDLED_CRITICAL_EXTENSION: Integer V_ERR_UNNESTED_RESOURCE: Integer V_ERR_UNSPECIFIED: Integer V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: Integer V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Integer V_ERR_UNSUPPORTED_EXTENSION_FEATURE: Integer V_ERR_UNSUPPORTED_NAME_SYNTAX: Integer V_FLAG_ALLOW_PROXY_CERTS: Integer V_FLAG_CHECK_SS_SIGNATURE: Integer V_FLAG_CRL_CHECK: Integer V_FLAG_CRL_CHECK_ALL: Integer V_FLAG_EXPLICIT_POLICY: Integer V_FLAG_EXTENDED_CRL_SUPPORT: Integer V_FLAG_IGNORE_CRITICAL: Integer V_FLAG_INHIBIT_ANY: Integer V_FLAG_INHIBIT_MAP: Integer V_FLAG_NOTIFY_POLICY: Integer V_FLAG_NO_ALT_CHAINS: Integer V_FLAG_NO_CHECK_TIME: Integer V_FLAG_PARTIAL_CHAIN: Integer V_FLAG_POLICY_CHECK: Integer V_FLAG_SUITEB_128_LOS: Integer V_FLAG_SUITEB_128_LOS_ONLY: Integer V_FLAG_SUITEB_192_LOS: Integer V_FLAG_TRUSTED_FIRST: Integer V_FLAG_USE_CHECK_TIME: Integer V_FLAG_USE_DELTAS: Integer V_FLAG_X509_STRICT: Integer V_OK: Integer class Attribute include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods public # # def ==: (instance other) -> bool # # def oid: () -> String # # def oid=: (String) -> String # # def to_der: () -> String # # def value: () -> ASN1::Set # # def value=: (ASN1::ASN1Data) -> ASN1::Set private # # def initialize: (String der) -> void | (String oid, ASN1::ASN1Data value) -> void # # def initialize_copy: (instance) -> void end class AttributeError < OpenSSL::OpenSSLError end class CRL include OpenSSL::X509::Extension::AuthorityKeyIdentifier include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods public # # def ==: (instance other) -> bool # # def add_extension: (Extension ext) -> Extension # # def add_revoked: (Revoked revoked) -> Revoked # # Gets X509v3 extensions as array of X509Ext objects # def extensions: () -> Array[Extension] # # Sets X509_EXTENSIONs # def extensions=: (Array[Extension] extensions) -> Array[Extension] # # def issuer: () -> X509::Name # # def issuer=: (X509::Name issuer) -> X509::Name # # def last_update: () -> Time? # # def last_update=: (Time last_update) -> Time # # def next_update: () -> Time? # # def next_update=: (Time next_update) -> Time # # def revoked: () -> Array[Revoked] # # def revoked=: (Array[Revoked]) -> Array[Revoked] # # def sign: (PKey::PKey key, Digest digest) -> String # # def signature_algorithm: () -> String # # def to_der: () -> String # # def to_pem: () -> String # # alias to_s to_pem # # def to_text: () -> String # # def verify: (PKey::PKey key) -> bool # # def version: () -> Integer # # def version=: (Integer) -> Integer private # # def initialize: (?String der) -> void # # def initialize_copy: (instance) -> void end class CRLError < OpenSSL::OpenSSLError end # # Implementation of an X.509 certificate as specified in RFC 5280. Provides # access to a certificate's attributes and allows certificates to be read from a # string, but also supports the creation of new certificates from scratch. # # ### Reading a certificate from a file # # Certificate is capable of handling DER-encoded certificates and certificates # encoded in OpenSSL's PEM format. # # raw = File.binread "cert.cer" # DER- or PEM-encoded # certificate = OpenSSL::X509::Certificate.new raw # # ### Saving a certificate to a file # # A certificate may be encoded in DER format # # cert = ... # File.open("cert.cer", "wb") { |f| f.print cert.to_der } # # or in PEM format # # cert = ... # File.open("cert.pem", "wb") { |f| f.print cert.to_pem } # # X.509 certificates are associated with a private/public key pair, typically a # RSA, DSA or ECC key (see also OpenSSL::PKey::RSA, OpenSSL::PKey::DSA and # OpenSSL::PKey::EC), the public key itself is stored within the certificate and # can be accessed in form of an OpenSSL::PKey. Certificates are typically used # to be able to associate some form of identity with a key pair, for example web # servers serving pages over HTTPs use certificates to authenticate themselves # to the user. # # The public key infrastructure (PKI) model relies on trusted certificate # authorities ("root CAs") that issue these certificates, so that end users need # to base their trust just on a selected few authorities that themselves again # vouch for subordinate CAs issuing their certificates to end users. # # The OpenSSL::X509 module provides the tools to set up an independent PKI, # similar to scenarios where the 'openssl' command line tool is used for issuing # certificates in a private PKI. # # ### Creating a root CA certificate and an end-entity certificate # # First, we need to create a "self-signed" root certificate. To do so, we need # to generate a key first. Please note that the choice of "1" as a serial number # is considered a security flaw for real certificates. Secure choices are # integers in the two-digit byte range and ideally not sequential but secure # random numbers, steps omitted here to keep the example concise. # # root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key # root_ca = OpenSSL::X509::Certificate.new # root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate # root_ca.serial = 1 # root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA" # root_ca.issuer = root_ca.subject # root CA's are "self-signed" # root_ca.public_key = root_key.public_key # root_ca.not_before = Time.now # root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity # ef = OpenSSL::X509::ExtensionFactory.new # ef.subject_certificate = root_ca # ef.issuer_certificate = root_ca # root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true)) # root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true)) # root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false)) # root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false)) # root_ca.sign(root_key, OpenSSL::Digest.new('SHA256')) # # The next step is to create the end-entity certificate using the root CA # certificate. # # key = OpenSSL::PKey::RSA.new 2048 # cert = OpenSSL::X509::Certificate.new # cert.version = 2 # cert.serial = 2 # cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate" # cert.issuer = root_ca.subject # root CA is the issuer # cert.public_key = key.public_key # cert.not_before = Time.now # cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity # ef = OpenSSL::X509::ExtensionFactory.new # ef.subject_certificate = cert # ef.issuer_certificate = root_ca # cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true)) # cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false)) # cert.sign(root_key, OpenSSL::Digest.new('SHA256')) # class Certificate include OpenSSL::X509::Extension::AuthorityInfoAccess include OpenSSL::X509::Extension::CRLDistributionPoints include OpenSSL::X509::Extension::AuthorityKeyIdentifier include OpenSSL::X509::Extension::SubjectKeyIdentifier include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods public # # Compares the two certificates. Note that this takes into account all fields, # not just the issuer name and the serial number. # def ==: (instance other) -> bool # # def add_extension: (Extension ext) -> Extension # # Returns `true` if *key* is the corresponding private key to the Subject Public # Key Information, `false` otherwise. # def check_private_key: (PKey::PKey key) -> bool # # def extensions: () -> Array[Extension] # # def extensions=: (Array[Extension]) -> Array[Extension] # # def inspect: () -> String # # def issuer: () -> Name # # def issuer=: (Name) -> Name # # def not_after: () -> Time? # # def not_after=: (Time) -> Time # # def not_before: () -> Time? # # def not_before=: (Time) -> Time # # def pretty_print: (untyped q) -> untyped # # def public_key: () -> PKey::PKey # # def public_key=: (PKey::PKey pkey) -> PKey::PKey # # def serial: () -> BN # # def serial=: (bn serial) -> bn # # def sign: (PKey::PKey key, String digest) -> String # # def signature_algorithm: () -> String # # def subject: () -> Name # # def subject=: (Name) -> Name # # def to_der: () -> String # # def to_pem: () -> String # # alias to_s to_pem # # def to_text: () -> String # # Verifies the signature of the certificate, with the public key *key*. *key* # must be an instance of OpenSSL::PKey. # def verify: (PKey::PKey key) -> bool # # def version: () -> Integer # # def version=: (Integer) -> Integer private # # def initialize: (?String pem) -> void # # def initialize_copy: (instance) -> void end class CertificateError < OpenSSL::OpenSSLError end class Extension include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods public # # def ==: (instance other) -> bool # # def critical=: [U] (boolish) -> U # # def critical?: () -> bool # # def oid: () -> String # # def oid=: (String oid) -> String # # def to_a: () -> [ String, String, bool ] # # def to_der: () -> String # # def to_h: () -> Hash[String, untyped] # # def to_s: () -> String # # def value: () -> String # # def value=: (String | ASN1::_ToDer data) -> String # # def value_der: () -> String private # # Creates an X509 extension. # # The extension may be created from *der* data or from an extension *oid* and # *value*. The *oid* may be either an OID or an extension name. If *critical* # is `true` the extension is marked critical. # def initialize: (String der) -> void | (String oid, String value, ?boolish critical) -> void # # def initialize_copy: (instance) -> void module AuthorityInfoAccess include OpenSSL::X509::Extension::Helpers public # # Get the information and services for the issuer from the certificate's # authority information access extension exteension, as described in RFC5280 # Section 4.2.2.1. # # Returns an array of strings or nil or raises ASN1::ASN1Error. # def ca_issuer_uris: () -> Array[String]? # # Get the URIs for OCSP from the certificate's authority information access # extension exteension, as described in RFC5280 Section 4.2.2.1. # # Returns an array of strings or nil or raises ASN1::ASN1Error. # def ocsp_uris: () -> Array[String]? private # # def parse_aia_asn1: () -> untyped end module AuthorityKeyIdentifier include OpenSSL::X509::Extension::Helpers public # # Get the issuing certificate's key identifier from the authorityKeyIdentifier # extension, as described in RFC5280 Section 4.2.1.1 # # Returns the binary String keyIdentifier or nil or raises ASN1::ASN1Error. # def authority_key_identifier: () -> String? end module CRLDistributionPoints include OpenSSL::X509::Extension::Helpers public # # Get the distributionPoint fullName URI from the certificate's CRL distribution # points extension, as described in RFC5280 Section 4.2.1.13 # # Returns an array of strings or nil or raises ASN1::ASN1Error. # def crl_uris: () -> Array[String]? end module Helpers public # # def find_extension: (String oid) -> Extension? end module SubjectKeyIdentifier include OpenSSL::X509::Extension::Helpers public # # Get the subject's key identifier from the subjectKeyIdentifier exteension, as # described in RFC5280 Section 4.2.1.2. # # Returns the binary String key identifier or nil or raises ASN1::ASN1Error. # def subject_key_identifier: () -> String? end end class ExtensionError < OpenSSL::OpenSSLError end class ExtensionFactory public def config: () -> Config? def config=: (Config config) -> Config # # Creates a new X509::Extension with passed values. See also x509v3_config(5). # def create_ext: (String oid, String value, ?boolish critical) -> Extension # # def create_ext_from_array: ([ String, String ] | [ String, String, boolish ] ary) -> Extension # # def create_ext_from_hash: (Hash[String, String | boolish] hash) -> Extension # # def create_ext_from_string: (String str) -> Extension # # def create_extension: (String oid, String value, ?boolish critical) -> Extension def crl: () -> CRL? # # def crl=: (CRL crl) -> CRL def issuer_certificate: () -> Certificate? # # def issuer_certificate=: (Certificate cert) -> Certificate def subject_certificate: () -> Certificate? # # def subject_certificate=: (Certificate cert) -> Certificate def subject_request: () -> Request? # # def subject_request=: (Request request) -> Request private # # def initialize: (?Certificate? issuer_cert, ?Certificate? subject_cert, ?Request? request, ?CRL? crl) -> void end # # An X.509 name represents a hostname, email address or other entity associated # with a public key. # # You can create a Name by parsing a distinguished name String or by supplying # the distinguished name as an Array. # # name = OpenSSL::X509::Name.parse_rfc2253 'DC=example,CN=nobody' # # name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']] # class Name type distinguished_name = [ String, String ] type template = Hash[String, Integer] include OpenSSL::Marshal include Comparable extend OpenSSL::Marshal::ClassMethods # # alias self.parse self.parse_openssl # # Parses the string representation of a distinguished name. Two different forms # are supported: # # * OpenSSL format (`X509_NAME_oneline()`) used by `#to_s`. For example: # `/DC=com/DC=example/CN=nobody` # * OpenSSL format (`X509_NAME_print()`) used by # `#to_s(OpenSSL::X509::Name::COMPAT)`. For example: `DC=com, DC=example, # CN=nobody` # # # Neither of them is standardized and has quirks and inconsistencies in handling # of escaped characters or multi-valued RDNs. # # Use of this method is discouraged in new applications. See Name.parse_rfc2253 # and #to_utf8 for the alternative. # def self.parse_openssl: (String str, ?template template) -> instance # # Parses the UTF-8 string representation of a distinguished name, according to # RFC 2253. # # See also #to_utf8 for the opposite operation. # def self.parse_rfc2253: (String str, ?template template) -> instance public # # Compares this Name with *other* and returns `0` if they are the same and `-1` # or `+1` if they are greater or less than each other respectively. Returns # `nil` if they are not comparable (i.e. different types). # alias <=> cmp # # Adds a new entry with the given *oid* and *value* to this name. The *oid* is # an object identifier defined in ASN.1. Some common OIDs are: # # C # : Country Name # CN # : Common Name # DC # : Domain Component # O # : Organization Name # OU # : Organizational Unit Name # ST # : State or Province Name # # # The optional keyword parameters *loc* and *set* specify where to insert the # new attribute. Refer to the manpage of X509_NAME_add_entry(3) for details. # *loc* defaults to -1 and *set* defaults to 0. This appends a single-valued RDN # to the end. # def add_entry: (String oid, String value, ?loc: Integer, ?set: Integer) -> self # # Compares this Name with *other* and returns `0` if they are the same and `-1` # or `+1` if they are greater or less than each other respectively. Returns # `nil` if they are not comparable (i.e. different types). # def cmp: (untyped other) -> Integer? # # Returns true if *name* and *other* refer to the same hash key. # def eql?: (instance other) -> bool # # The hash value returned is suitable for use as a certificate's filename in a # CA path. # def hash: () -> Integer # # Returns an MD5 based hash used in OpenSSL 0.9.X. # def hash_old: () -> Integer def inspect: () -> String # # def pretty_print: (untyped q) -> untyped # # Returns an Array representation of the distinguished name suitable for passing # to ::new # def to_a: () -> Array[[ String, String, Integer ]] # # Converts the name to DER encoding # def to_der: () -> String # # Returns a String representation of the Distinguished Name. *format* is one of: # # * OpenSSL::X509::Name::COMPAT # * OpenSSL::X509::Name::RFC2253 # * OpenSSL::X509::Name::ONELINE # * OpenSSL::X509::Name::MULTILINE # # # If *format* is omitted, the largely broken and traditional OpenSSL format # (`X509_NAME_oneline()` format) is chosen. # # **Use of this method is discouraged.** None of the formats other than # OpenSSL::X509::Name::RFC2253 is standardized and may show an inconsistent # behavior through OpenSSL versions. # # It is recommended to use #to_utf8 instead, which is equivalent to calling # `name.to_s(OpenSSL::X509::Name::RFC2253).force_encoding("UTF-8")`. # def to_s: (?format format) -> String # # Returns an UTF-8 representation of the distinguished name, as specified in # [RFC 2253](https://www.ietf.org/rfc/rfc2253.txt). # def to_utf8: () -> String private # # Creates a new Name. # # A name may be created from a DER encoded string *der*, an Array representing a # *distinguished_name* or a *distinguished_name* along with a *template*. # # name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']] # # name = OpenSSL::X509::Name.new name.to_der # # See add_entry for a description of the *distinguished_name* Array's contents # def initialize: (distinguished_name name, template template) -> void | (Array[distinguished_name] names) -> void | (?String der) -> void # # def initialize_copy: (instance) -> void # # A flag for #to_s. # # Breaks the name returned into multiple lines if longer than 80 characters. # COMPAT: Integer # # The default object type for name entries. # DEFAULT_OBJECT_TYPE: Integer # # A flag for #to_s. # # Returns a multiline format. # MULTILINE: Integer # # The default object type template for name entries. # OBJECT_TYPE_TEMPLATE: template # # A flag for #to_s. # # Returns a more readable format than RFC2253. # ONELINE: Integer # # A flag for #to_s. # # Returns an RFC2253 format name. # RFC2253: Integer type format = Integer module RFC2253DN def self.expand_hexstring: (untyped str) -> untyped def self.expand_pair: (untyped str) -> untyped def self.expand_value: (untyped str1, untyped str2, untyped str3) -> untyped def self.scan: (untyped dn) -> untyped private # # def expand_hexstring: (untyped str) -> untyped # # def expand_pair: (untyped str) -> untyped # # def expand_value: (untyped str1, untyped str2, untyped str3) -> untyped # # def scan: (String dn) -> Array[distinguished_name] AttributeType: Regexp AttributeValue: Regexp HexChar: Regexp HexPair: Regexp HexString: Regexp Pair: Regexp QuoteChar: Regexp Special: String StringChar: Regexp TypeAndValue: Regexp end end class NameError < OpenSSL::OpenSSLError end class Request include OpenSSL::Marshal extend OpenSSL::Marshal::ClassMethods public # # def ==: (untyped other) -> bool # # def add_attribute: (Attribute attribute) -> Attribute # # def attributes: () -> Array[Attribute] # # def attributes=: (Array[Attribute] attributes) -> Array[Attribute] # # def public_key: () -> PKey::PKey # # def public_key=: (PKey::PKey public_key) -> PKey::PKey # # def sign: (PKey::PKey key, Digest | String digest) -> String # # def signature_algorithm: () -> String # # def subject: () -> Name # # def subject=: (Name subject) -> Name # # def to_der: () -> String # # def to_pem: () -> String # # alias to_s to_pem # # def to_text: () -> String # # Checks that cert signature is made with PRIVversion of this PUBLIC 'key' # def verify: (PKey::PKey key) -> bool # # def version: () -> Integer # # def version=: (Integer version) -> Integer private # # def initialize: (?String der) -> void # # def initialize_copy: (instance) -> void end class RequestError < OpenSSL::OpenSSLError end class Revoked public # # def ==: (untyped other) -> bool # # def add_extension: (Extension ext) -> Extension # # Gets X509v3 extensions as array of X509Ext objects # def extensions: () -> Array[Extension] # # Sets X509_EXTENSIONs # def extensions=: (Array[Extension] extensions) -> Array[Extension] # # def serial: () -> Integer # # def serial=: (Integer integer) -> Integer # # def time: () -> Time? # # def time=: (Time time) -> Time # # def to_der: () -> String private # # def initialize: (*untyped) -> void # # def initialize_copy: (instance) -> void end class RevokedError < OpenSSL::OpenSSLError end # # The X509 certificate store holds trusted CA certificates used to verify peer # certificates. # # The easiest way to create a useful certificate store is: # # cert_store = OpenSSL::X509::Store.new # cert_store.set_default_paths # # This will use your system's built-in certificates. # # If your system does not have a default set of certificates you can obtain a # set extracted from Mozilla CA certificate store by cURL maintainers here: # https://curl.haxx.se/docs/caextract.html (You may wish to use the # firefox-db2pem.sh script to extract the certificates from a local install to # avoid man-in-the-middle attacks.) # # After downloading or generating a cacert.pem from the above link you can # create a certificate store from the pem file like this: # # cert_store = OpenSSL::X509::Store.new # cert_store.add_file 'cacert.pem' # # The certificate store can be used with an SSLSocket like this: # # ssl_context = OpenSSL::SSL::SSLContext.new # ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER # ssl_context.cert_store = cert_store # # tcp_socket = TCPSocket.open 'example.com', 443 # # ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context # class Store public # # Adds the OpenSSL::X509::Certificate *cert* to the certificate store. # # See also the man page X509_STORE_add_cert(3). # def add_cert: (Certificate certificate) -> self # # Adds the OpenSSL::X509::CRL *crl* to the store. # # See also the man page X509_STORE_add_crl(3). # def add_crl: (CRL crl) -> self # # Adds the certificates in *file* to the certificate store. *file* is the path # to the file, and the file contains one or more certificates in PEM format # concatenated together. # # See also the man page X509_LOOKUP_file(3). # def add_file: (String file) -> self # # Adds *path* as the hash dir to be looked up by the store. # # See also the man page X509_LOOKUP_hash_dir(3). # def add_path: (String path) -> self # # The certificate chain constructed by the last call of #verify. # # See also StoreContext#chain. # def chain: () -> Array[Certificate]? # # The error code set by the last call of #verify. # # See also StoreContext#error. # def error: () -> Integer? # # The description for the error code set by the last call of #verify. # # See also StoreContext#error_string. # def error_string: () -> String? # # Sets the default flags used by certificate chain verification performed with # the Store. # # *flags* consists of zero or more of the constants defined in OpenSSL::X509 # with name V_FLAG_* or'ed together. # # OpenSSL::X509::StoreContext#flags= can be used to change the flags for a # single verification operation. # # See also the man page X509_VERIFY_PARAM_set_flags(3). # def flags=: (Integer flags) -> Integer # # Sets the store's default verification purpose. If specified, the verifications # on the store will check every certificate's extensions are consistent with the # purpose. The purpose is specified by constants: # # * X509::PURPOSE_SSL_CLIENT # * X509::PURPOSE_SSL_SERVER # * X509::PURPOSE_NS_SSL_SERVER # * X509::PURPOSE_SMIME_SIGN # * X509::PURPOSE_SMIME_ENCRYPT # * X509::PURPOSE_CRL_SIGN # * X509::PURPOSE_ANY # * X509::PURPOSE_OCSP_HELPER # * X509::PURPOSE_TIMESTAMP_SIGN # # # OpenSSL::X509::StoreContext#purpose= can be used to change the value for a # single verification operation. # # See also the man page X509_VERIFY_PARAM_set_purpose(3). # def purpose=: (Integer purpose) -> Integer # # Configures *store* to look up CA certificates from the system default # certificate store as needed basis. The location of the store can usually be # determined by: # # * OpenSSL::X509::DEFAULT_CERT_FILE # * OpenSSL::X509::DEFAULT_CERT_DIR # # # See also the man page X509_STORE_set_default_paths(3). # def set_default_paths: () -> nil # # Sets the time to be used in the certificate verifications with the store. By # default, if not specified, the current system time is used. # # OpenSSL::X509::StoreContext#time= can be used to change the value for a single # verification operation. # # See also the man page X509_VERIFY_PARAM_set_time(3). # def time=: (Time time) -> Time # # Sets the default trust settings used by the certificate verification with the # store. # # OpenSSL::X509::StoreContext#trust= can be used to change the value for a # single verification operation. # # See also the man page X509_VERIFY_PARAM_set_trust(3). # def trust=: (Integer trust) -> Integer # # Performs a certificate verification on the OpenSSL::X509::Certificate *cert*. # # *chain* can be an array of OpenSSL::X509::Certificate that is used to # construct the certificate chain. # # If a block is given, it overrides the callback set by #verify_callback=. # # After finishing the verification, the error information can be retrieved by # #error, #error_string, and the resulting complete certificate chain can be # retrieved by #chain. # def verify: (Certificate certificate, ?Array[Certificate] chain) ?{ (bool preverify_ok, StoreContext store_ctx) -> boolish } -> boolish # # The callback for additional certificate verification. It is invoked for each # certificate in the chain and can be used to implement custom certificate # verification conditions. # # The callback is invoked with two values, a boolean that indicates if the # pre-verification by OpenSSL has succeeded or not, and the StoreContext in use. # # The callback can use StoreContext#error= to change the error code as needed. # The callback must return either true or false. # # NOTE: any exception raised within the callback will be ignored. # # See also the man page X509_STORE_CTX_set_verify_cb(3). # def verify_callback: () -> (^(bool preverify_ok, StoreContext store_ctx) -> boolish | nil) # # General callback for OpenSSL verify # def verify_callback=: [U] (^(bool preverify_ok, StoreContext store_ctx) -> boolish) -> U private # # Creates a new X509::Store. # def initialize: () -> void end # # A StoreContext is used while validating a single certificate and holds the # status involved. # class StoreContext public # # Returns the verified chain. # # See also the man page X509_STORE_CTX_set0_verified_chain(3). # def chain: () -> Array[Certificate]? # # def cleanup: () -> void # # Returns the certificate which caused the error. # # See also the man page X509_STORE_CTX_get_current_cert(3). # def current_cert: () -> Certificate # # Returns the CRL which caused the error. # # See also the man page X509_STORE_CTX_get_current_crl(3). # def current_crl: () -> CRL # # Returns the error code of *stctx*. This is typically called after #verify is # done, or from the verification callback set to # OpenSSL::X509::Store#verify_callback=. # # See also the man page X509_STORE_CTX_get_error(3). # def error: () -> Integer? # # Sets the error code of *stctx*. This is used by the verification callback set # to OpenSSL::X509::Store#verify_callback=. # # See also the man page X509_STORE_CTX_set_error(3). # def error=: (Integer error) -> Integer # # Returns the depth of the chain. This is used in combination with #error. # # See also the man page X509_STORE_CTX_get_error_depth(3). # def error_depth: () -> Integer # # Returns the human readable error string corresponding to the error code # retrieved by #error. # # See also the man page X509_verify_cert_error_string(3). # def error_string: () -> String? # # Sets the verification flags to the context. This overrides the default value # set by Store#flags=. # # See also the man page X509_VERIFY_PARAM_set_flags(3). # def flags=: (Integer flags) -> Integer # # Sets the purpose of the context. This overrides the default value set by # Store#purpose=. # # See also the man page X509_VERIFY_PARAM_set_purpose(3). # def purpose=: (Integer purpose) -> Integer # # Sets the time used in the verification. If not set, the current time is used. # # See also the man page X509_VERIFY_PARAM_set_time(3). # def time=: (Time time) -> Time # # Sets the trust settings of the context. This overrides the default value set # by Store#trust=. # # See also the man page X509_VERIFY_PARAM_set_trust(3). # def trust=: (Integer trust) -> Integer # # Performs the certificate verification using the parameters set to *stctx*. # # See also the man page X509_verify_cert(3). # def verify: () -> bool private # # Sets up a StoreContext for a verification of the X.509 certificate *cert*. # def initialize: (Store store, ?Certificate cert, ?Array[Certificate] chain) -> void end class StoreError < OpenSSL::OpenSSLError end end end