# <!-- rdoc-file=ext/openssl/ossl.c -->
# 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
  # <!--
  #   rdoc-file=ext/openssl/lib/openssl/digest.rb
  #   - Digest(name)
  # -->
  # 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)

  # <!--
  #   rdoc-file=ext/openssl/ossl.c
  #   - OpenSSL.debug -> true | false
  # -->
  #
  def self.debug: () -> bool

  # <!--
  #   rdoc-file=ext/openssl/ossl.c
  #   - OpenSSL.debug = boolean -> boolean
  # -->
  # 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

  # <!--
  #   rdoc-file=ext/openssl/ossl.c
  #   - OpenSSL.errors -> [String...]
  # -->
  # 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]

  # <!--
  #   rdoc-file=ext/openssl/ossl.c
  #   - OpenSSL.fips_mode -> true | false
  # -->
  #
  def self.fips_mode: () -> bool

  # <!--
  #   rdoc-file=ext/openssl/ossl.c
  #   - OpenSSL.fips_mode = boolean -> boolean
  # -->
  # 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

  # <!--
  #   rdoc-file=ext/openssl/ossl.c
  #   - OpenSSL.fixed_length_secure_compare(string, string) -> boolean
  # -->
  # 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

  # <!--
  #   rdoc-file=ext/openssl/lib/openssl.rb
  #   - OpenSSL.secure_compare(string, string) -> boolean
  # -->
  # 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

  # <!-- rdoc-file=ext/openssl/ossl.c -->
  # Boolean indicating whether OpenSSL is FIPS-capable or not
  #
  OPENSSL_FIPS: bool

  OPENSSL_LIBRARY_VERSION: String

  # <!-- rdoc-file=ext/openssl/ossl.c -->
  # Version of OpenSSL the ruby OpenSSL extension was built with
  #
  OPENSSL_VERSION: String

  # <!-- rdoc-file=ext/openssl/ossl.c -->
  # Version number of OpenSSL the ruby OpenSSL extension was built with (base 16)
  #
  OPENSSL_VERSION_NUMBER: Integer

  VERSION: String

  # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
  # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_asn1.c
    #   - OpenSSL::ASN1.decode(der) -> ASN1Data
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_asn1.c
    #   - OpenSSL::ASN1.decode_all(der) -> Array of 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]

    # <!--
    #   rdoc-file=ext/openssl/ossl_asn1.c
    #   - OpenSSL::ASN1.traverse(asn1) -> nil
    # -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
    # 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 => #<OpenSSL::ASN1::Sequence:0x87326e0
    #     #              @indefinite_length=false,
    #     #              @tag=16,
    #     #              @tag_class=:UNIVERSAL,
    #     #              @tagging=nil,
    #     #              @value=
    #     #                [#<OpenSSL::ASN1::ASN1Data:0x87326f4
    #     #                   @indefinite_length=false,
    #     #                   @tag=0,
    #     #                   @tag_class=:CONTEXT_SPECIFIC,
    #     #                   @value="\x01">]>
    #     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 => #<OpenSSL::ASN1::Sequence:0x87326e0
    #     #              @indefinite_length=false,
    #     #              @tag=16,
    #     #              @tag_class=:UNIVERSAL,
    #     #              @tagging=nil,
    #     #              @value=
    #     #                [#<OpenSSL::ASN1::ASN1Data:0x87326f4
    #     #                   @indefinite_length=false,
    #     #                   @tag=0,
    #     #                   @tag_class=:CONTEXT_SPECIFIC,
    #     #                   @value=
    #     #                     [#<OpenSSL::ASN1::Integer:0x85bf308
    #     #                        @indefinite_length=false,
    #     #                        @tag=2,
    #     #                        @tag_class=:UNIVERSAL
    #     #                        @tagging=nil,
    #     #                        @value=1>]>]>
    #     int2 = asn1.value[0].value[0]
    #     puts int2.value # => 1
    #
    class ASN1Data
      public

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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=

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # An Integer representing the tag number of this ASN1Data. Never `nil`.
      #
      def tag: () -> bn

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # An Integer representing the tag number of this ASN1Data. Never `nil`.
      #
      def tag=: (::Integer) -> ::Integer
              | (BN) -> BN

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # A Symbol representing the tag class of this ASN1Data. Never `nil`. See
      # ASN1Data for possible values.
      #
      def tag_class: () -> tag_class

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # A Symbol representing the tag class of this ASN1Data. Never `nil`. See
      # ASN1Data for possible values.
      #
      def tag_class=: (tag_class) -> tag_class

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - asn1.to_der => DER-encoded String
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data
      # -->
      # *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

    # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - asn1_ary.each { |asn1| block } => asn1_ary
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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?

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - asn1.to_der => DER-encoded String
      # -->
      # See ASN1Data#to_der for details.
      #
      def to_der: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive
      # -->
      # *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

    # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
    # Represents the primitive object id for OpenSSL::ASN1
    #
    class ObjectId < OpenSSL::ASN1::Primitive
      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name)
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - oid == other_oid => true or false
      # -->
      # Returns `true` if *other_oid* is the same as *oid*
      #
      def ==: (ObjectId other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - oid.ln -> string
      #   - oid.long_name -> string
      # -->
      # The long name of the ObjectId, as defined in <openssl/objects.h>.
      #
      def ln: () -> String?

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # The long name of the ObjectId, as defined in <openssl/objects.h>.
      #
      alias long_name ln

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - oid.oid -> string
      # -->
      # Returns a String representing the Object Identifier in the dot notation, e.g.
      # "1.2.3.4.5"
      #
      def oid: () -> String

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # The short name of the ObjectId, as defined in <openssl/objects.h>.
      #
      alias short_name sn

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - oid.sn -> string
      #   - oid.short_name -> string
      # -->
      # The short name of the ObjectId, as defined in <openssl/objects.h>.
      #
      def sn: () -> String?
    end

    class OctetString < OpenSSL::ASN1::Primitive
      def value: () -> String

      def value=: (String) -> String
    end

    # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
    # 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 <openssl/objects.h>.
    # *   *ln*: the long name as defined in <openssl/objects.h>.
    # *   *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 = <class>.new(value) # <class> being one of the sub-classes except EndOfContent
    #     prim_zero_tagged_implicit = <class>.new(value, 0, :IMPLICIT)
    #     prim_zero_tagged_explicit = <class>.new(value, 0, :EXPLICIT)
    #
    class Primitive < OpenSSL::ASN1::ASN1Data
      public

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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?

      # <!-- rdoc-file=ext/openssl/ossl_asn1.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - asn1.to_der => DER-encoded String
      # -->
      # See ASN1Data#to_der for details.
      #
      def to_der: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_asn1.c
      #   - OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive
      # -->
      # *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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - BN.rand(bits [, fill [, odd]]) -> aBN
    # -->
    # Generates a cryptographically strong pseudo-random number of `bits`.
    #
    # See also the man page BN_rand(3).
    #
    def self.rand: (*untyped) -> untyped

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - BN.rand_range(range) -> aBN
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn % bn2 => aBN
    # -->
    #
    def %: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn * bn2 => aBN
    # -->
    #
    def *: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn ** bn2 => aBN
    # -->
    #
    def **: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn + bn2 => aBN
    # -->
    #
    def +: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - +bn -> aBN
    # -->
    #
    def +@: () -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn - bn2 => aBN
    # -->
    #
    def -: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - -bn -> aBN
    # -->
    #
    def -@: () -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn1 / bn2 => [result, remainder]
    # -->
    # Division of OpenSSL::BN instances
    #
    def /: (int) -> [ instance, instance ]

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn << bits -> aBN
    # -->
    #
    def <<: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - <=>(p1)
    # -->
    #
    alias <=> cmp

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn == obj => true or false
    # -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_bn.c -->
    # 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 === ==

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn >> bits -> aBN
    # -->
    #
    def >>: (int) -> int

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.bit_set?(bit) => true | false
    # -->
    # Tests bit *bit* in *bn* and returns `true` if set, `false` if not set.
    #
    def bit_set?: (int) -> bool

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.clear_bit!(bit) -> self
    # -->
    #
    def clear_bit!: (int) -> void

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.cmp(bn2) => integer
    # -->
    #
    def cmp: (Integer) -> Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - coerce(p1)
    # -->
    #
    def coerce: (::Integer) -> Array[Integer]
              | (BN) -> Array[BN]

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - copy(p1)
    # -->
    #
    def copy: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.eql?(obj) => true or false
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.gcd(bn2) => aBN
    # -->
    #
    def gcd: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.hash => Integer
    # -->
    # Returns a hash code for this object.
    #
    # See also Object#hash.
    #
    def hash: () -> Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.lshift!(bits) -> self
    # -->
    #
    def lshift!: (int bits) -> self

    def mask_bits!: (int) -> void

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.mod_add(bn1, bn2) -> aBN
    # -->
    #
    def mod_add: (int, int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.mod_exp(bn1, bn2) -> aBN
    # -->
    #
    def mod_exp: (int, int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.mod_inverse(bn2) => aBN
    # -->
    #
    def mod_inverse: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.mod_mul(bn1, bn2) -> aBN
    # -->
    #
    def mod_mul: (int, int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.mod_sqr(bn2) => aBN
    # -->
    #
    def mod_sqr: (int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.mod_sub(bn1, bn2) -> aBN
    # -->
    #
    def mod_sub: (int, int) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.negative? => true | false
    # -->
    #
    def negative?: () -> bool

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.num_bits => integer
    # -->
    #
    def num_bits: () -> ::Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.num_bytes => integer
    # -->
    #
    def num_bytes: () -> ::Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.odd? => true | false
    # -->
    #
    def odd?: () -> bool

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.one? => true | false
    # -->
    #
    def one?: () -> bool

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/bn.rb
    #   - pretty_print(q)
    # -->
    #
    def pretty_print: (untyped q) -> untyped

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.prime? => true | false
    #   - bn.prime?(checks) => true | false
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.prime_fasttest? => true | false
    #   - bn.prime_fasttest?(checks) => true | false
    #   - bn.prime_fasttest?(checks, trial_div) => true | false
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.rshift!(bits) -> self
    # -->
    #
    def rshift!: (int bits) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.set_bit!(bit) -> self
    # -->
    #
    def set_bit!: (int bit) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.sqr => aBN
    # -->
    #
    def sqr: () -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - to_bn()
    # -->
    #
    def to_bn: () -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.to_i => integer
    # -->
    #
    def to_i: () -> ::Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - to_int()
    # -->
    #
    alias to_int to_i

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.to_s(base = 10) -> string
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.ucmp(bn2) => integer
    # -->
    #
    def ucmp: (int bn2) -> ::Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - bn.zero? => true | false
    # -->
    #
    def zero?: () -> bool

    private

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - OpenSSL::BN.new(bn) -> aBN
    #   - OpenSSL::BN.new(integer) -> aBN
    #   - OpenSSL::BN.new(string, base = 10) -> aBN
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_bn.c
    #   - initialize_copy(p1)
    # -->
    #
    def initialize_copy: (instance other) -> instance
  end

  # <!-- rdoc-file=ext/openssl/ossl_bn.c -->
  # Generic Error for all of OpenSSL::BN (big num)
  #
  class BNError < OpenSSL::OpenSSLError
  end

  # <!-- rdoc-file=ext/openssl/lib/openssl/buffering.rb -->
  # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - <<(s)
    # -->
    # Writes *s* to the stream.  *s* will be converted to a String using `.to_s`
    # method.
    #
    def <<: (String s) -> self

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - close()
    # -->
    # Closes the SSLSocket and flushes any unwritten data.
    #
    def close: () -> void

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - each(eol=$/) { |line| ... }
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - each_byte() { |byte| ... }
    # -->
    # Calls the given block once for each byte in the stream.
    #
    def each_byte: () ?{ (Integer) -> void } -> void

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - each_line(eol=$/)
    # -->
    #
    alias each_line each

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - eof()
    # -->
    #
    alias eof eof?

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - eof?()
    # -->
    # Returns true if the stream is at file which means there is no more data to be
    # read.
    #
    def eof?: () -> bool

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - flush()
    # -->
    # Flushes buffered data to the SSLSocket.
    #
    def flush: () -> self

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - getc()
    # -->
    # Reads one character from the stream.  Returns nil if called at end of file.
    #
    def getc: () -> String?

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - gets(eol=$/, limit=nil)
    # -->
    # 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?

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - print(*args)
    # -->
    # Writes *args* to the stream.
    #
    # See IO#print for full details.
    #
    def print: (*untyped args) -> nil

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - printf(s, *args)
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - puts(*args)
    # -->
    # Writes *args* to the stream along with a record separator.
    #
    # See IO#puts for full details.
    #
    def puts: (*untyped args) -> nil

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - read(size=nil, buf=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?

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - read_nonblock(maxlen, buf=nil, exception: true)
    # -->
    # 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)

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - readchar()
    # -->
    # Reads a one-character string from the stream.  Raises an EOFError at end of
    # file.
    #
    def readchar: () -> String

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - readline(eol=$/)
    # -->
    # Reads a line from the stream which is separated by *eol*.
    #
    # Raises EOFError if at end of file.
    #
    def readline: (?String eol) -> String

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - readlines(eol=$/)
    # -->
    # Reads lines from the stream which are separated by *eol*.
    #
    # See also #gets
    #
    def readlines: (?String eol) -> ::Array[String]

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - readpartial(maxlen, buf=nil)
    # -->
    # 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

    # <!-- rdoc-file=ext/openssl/lib/openssl/buffering.rb -->
    # The "sync mode" of the SSLSocket.
    #
    # See IO#sync for full details.
    #
    def sync: () -> bool

    # <!-- rdoc-file=ext/openssl/lib/openssl/buffering.rb -->
    # The "sync mode" of the SSLSocket.
    #
    # See IO#sync for full details.
    #
    def sync=: (boolish) -> void

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - ungetc(c)
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - write(*s)
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - write_nonblock(s, exception: true)
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - consume_rbuff(size=nil)
    # -->
    # Consumes *size* bytes from the buffer
    #
    def consume_rbuff: (?untyped size) -> untyped

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - do_write(s)
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
    #   - fill_rbuff()
    # -->
    # Fills the buffer from the underlying SSLSocket
    #
    def fill_rbuff: () -> untyped

    # <!-- rdoc-file=ext/openssl/lib/openssl/buffering.rb -->
    # Default size to read from or write to the SSLSocket for buffer operations.
    #
    BLOCK_SIZE: Integer

    # <!-- rdoc-file=ext/openssl/lib/openssl/buffering.rb -->
    # A buffer which will retain binary encoding.
    #
    class Buffer < String
      BINARY: Encoding

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
      #   - <<(string)
      # -->
      #
      def <<: (String string) -> self

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/buffering.rb
      #   - concat(string)
      # -->
      #
      alias concat <<
    end
  end

  # <!-- rdoc-file=ext/openssl/ossl_cipher.c -->
  # Provides symmetric algorithms for encryption and decryption. The algorithms
  # that are available depend on the particular version of OpenSSL that is
  # installed.
  #
  # ### Listing all supported algorithms
  #
  # A list of supported algorithms can be obtained by
  #
  #     puts OpenSSL::Cipher.ciphers
  #
  # ### Instantiating a Cipher
  #
  # There are several ways to create a Cipher instance. Generally, a Cipher
  # algorithm is categorized by its name, the key length in bits and the cipher
  # mode to be used. The most generic way to create a Cipher is the following
  #
  #     cipher = OpenSSL::Cipher.new('<name>-<key length>-<mode>')
  #
  # That is, a string consisting of the hyphenated concatenation of the individual
  # components name, key length and mode. Either all uppercase or all lowercase
  # strings may be used, for example:
  #
  #     cipher = OpenSSL::Cipher.new('aes-128-cbc')
  #
  # ### Choosing either encryption or decryption mode
  #
  # Encryption and decryption are often very similar operations for symmetric
  # algorithms, this is reflected by not having to choose different classes for
  # either operation, both can be done using the same class. Still, after
  # obtaining a Cipher instance, we need to tell the instance what it is that we
  # intend to do with it, so we need to call either
  #
  #     cipher.encrypt
  #
  # or
  #
  #     cipher.decrypt
  #
  # on the Cipher instance. This should be the first call after creating the
  # instance, otherwise configuration that has already been set could get lost in
  # the process.
  #
  # ### Choosing a key
  #
  # Symmetric encryption requires a key that is the same for the encrypting and
  # for the decrypting party and after initial key establishment should be kept as
  # private information. There are a lot of ways to create insecure keys, the most
  # notable is to simply take a password as the key without processing the
  # password further. A simple and secure way to create a key for a particular
  # Cipher is
  #
  #     cipher = OpenSSL::Cipher.new('aes-256-cfb')
  #     cipher.encrypt
  #     key = cipher.random_key # also sets the generated key on the Cipher
  #
  # If you absolutely need to use passwords as encryption keys, you should use
  # Password-Based Key Derivation Function 2 (PBKDF2) by generating the key with
  # the help of the functionality provided by OpenSSL::PKCS5.pbkdf2_hmac_sha1 or
  # OpenSSL::PKCS5.pbkdf2_hmac.
  #
  # Although there is Cipher#pkcs5_keyivgen, its use is deprecated and it should
  # only be used in legacy applications because it does not use the newer PKCS#5
  # v2 algorithms.
  #
  # ### Choosing an IV
  #
  # The cipher modes CBC, CFB, OFB and CTR all need an "initialization vector", or
  # short, IV. ECB mode is the only mode that does not require an IV, but there is
  # almost no legitimate use case for this mode because of the fact that it does
  # not sufficiently hide plaintext patterns. Therefore
  #
  # **You should never use ECB mode unless you are absolutely sure that you
  # absolutely need it**
  #
  # Because of this, you will end up with a mode that explicitly requires an IV in
  # any case. Although the IV can be seen as public information, i.e. it may be
  # transmitted in public once generated, it should still stay unpredictable to
  # prevent certain kinds of attacks. Therefore, ideally
  #
  # **Always create a secure random IV for every encryption of your Cipher**
  #
  # A new, random IV should be created for every encryption of data. Think of the
  # IV as a nonce (number used once) - it's public but random and unpredictable. A
  # secure random IV can be created as follows
  #
  #     cipher = ...
  #     cipher.encrypt
  #     key = cipher.random_key
  #     iv = cipher.random_iv # also sets the generated IV on the Cipher
  #
  # Although the key is generally a random value, too, it is a bad choice as an
  # IV. There are elaborate ways how an attacker can take advantage of such an IV.
  # As a general rule of thumb, exposing the key directly or indirectly should be
  # avoided at all cost and exceptions only be made with good reason.
  #
  # ### Calling Cipher#final
  #
  # ECB (which should not be used) and CBC are both block-based modes. This means
  # that unlike for the other streaming-based modes, they operate on fixed-size
  # blocks of data, and therefore they require a "finalization" step to produce or
  # correctly decrypt the last block of data by appropriately handling some form
  # of padding. Therefore it is essential to add the output of
  # OpenSSL::Cipher#final to your encryption/decryption buffer or you will end up
  # with decryption errors or truncated data.
  #
  # Although this is not really necessary for streaming-mode ciphers, it is still
  # recommended to apply the same pattern of adding the output of Cipher#final
  # there as well - it also enables you to switch between modes more easily in the
  # future.
  #
  # ### Encrypting and decrypting some data
  #
  #     data = "Very, very confidential data"
  #
  #     cipher = OpenSSL::Cipher.new('aes-128-cbc')
  #     cipher.encrypt
  #     key = cipher.random_key
  #     iv = cipher.random_iv
  #
  #     encrypted = cipher.update(data) + cipher.final
  #     ...
  #     decipher = OpenSSL::Cipher.new('aes-128-cbc')
  #     decipher.decrypt
  #     decipher.key = key
  #     decipher.iv = iv
  #
  #     plain = decipher.update(encrypted) + decipher.final
  #
  #     puts data == plain #=> true
  #
  # ### Authenticated Encryption and Associated Data (AEAD)
  #
  # If the OpenSSL version used supports it, an Authenticated Encryption mode
  # (such as GCM or CCM) should always be preferred over any unauthenticated mode.
  # Currently, OpenSSL supports AE only in combination with Associated Data (AEAD)
  # where additional associated data is included in the encryption process to
  # compute a tag at the end of the encryption. This tag will also be used in the
  # decryption process and by verifying its validity, the authenticity of a given
  # ciphertext is established.
  #
  # This is superior to unauthenticated modes in that it allows to detect if
  # somebody effectively changed the ciphertext after it had been encrypted. This
  # prevents malicious modifications of the ciphertext that could otherwise be
  # exploited to modify ciphertexts in ways beneficial to potential attackers.
  #
  # An associated data is used where there is additional information, such as
  # headers or some metadata, that must be also authenticated but not necessarily
  # need to be encrypted. If no associated data is needed for encryption and later
  # decryption, the OpenSSL library still requires a value to be set - "" may be
  # used in case none is available.
  #
  # An example using the GCM (Galois/Counter Mode). You have 16 bytes *key*, 12
  # bytes (96 bits) *nonce* and the associated data *auth_data*. Be sure not to
  # reuse the *key* and *nonce* pair. Reusing an nonce ruins the security
  # guarantees of GCM mode.
  #
  #     cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
  #     cipher.key = key
  #     cipher.iv = nonce
  #     cipher.auth_data = auth_data
  #
  #     encrypted = cipher.update(data) + cipher.final
  #     tag = cipher.auth_tag # produces 16 bytes tag by default
  #
  # Now you are the receiver. You know the *key* and have received *nonce*,
  # *auth_data*, *encrypted* and *tag* through an untrusted network. Note that GCM
  # accepts an arbitrary length tag between 1 and 16 bytes. You may additionally
  # need to check that the received tag has the correct length, or you allow
  # attackers to forge a valid single byte tag for the tampered ciphertext with a
  # probability of 1/256.
  #
  #     raise "tag is truncated!" unless tag.bytesize == 16
  #     decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt
  #     decipher.key = key
  #     decipher.iv = nonce
  #     decipher.auth_tag = tag
  #     decipher.auth_data = auth_data
  #
  #     decrypted = decipher.update(encrypted) + decipher.final
  #
  #     puts data == decrypted #=> true
  #
  class Cipher
    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - OpenSSL::Cipher.ciphers -> array[string...]
    # -->
    # Returns the names of all available ciphers in an array.
    #
    def self.ciphers: () -> Array[String]

    public

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.auth_data = string -> string
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.auth_tag(tag_len = 16) -> 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.auth_tag = string -> 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.auth_tag_len = Integer -> Integer
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.authenticated? -> true | false
    # -->
    # Indicated whether this Cipher instance uses an Authenticated Encryption mode.
    #
    def authenticated?: () -> bool

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.block_size -> integer
    # -->
    # Returns the size in bytes of the blocks on which this Cipher operates on.
    #
    def block_size: () -> Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.decrypt -> self
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.encrypt -> 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.final -> string
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.iv = string -> 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.iv_len -> integer
    # -->
    # Returns the expected length in bytes for an IV for this Cipher.
    #
    def iv_len: () -> Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.iv_len = integer -> 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.key = string -> string
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.key_len -> integer
    # -->
    # Returns the key length in bytes of the Cipher.
    #
    def key_len: () -> Integer

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.key_len = integer -> 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.name -> string
    # -->
    # Returns the name of the cipher which may differ slightly from the original
    # name provided.
    #
    def name: () -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.padding = integer -> integer
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.pkcs5_keyivgen(pass, salt = nil, iterations = 2048, digest = "MD5") -> nil
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/cipher.rb
    #   - cipher.random_iv -> iv
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/cipher.rb
    #   - cipher.random_key -> key
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.reset -> self
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - cipher.update(data [, buffer]) -> string or buffer
    # -->
    # 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]

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - Cipher.new(string) -> cipher
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_cipher.c
    #   - initialize_copy(p1)
    # -->
    #
    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

    # <!-- rdoc-file=ext/openssl/lib/openssl/cipher.rb -->
    # 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

  # <!-- rdoc-file=ext/openssl/ossl_config.c -->
  # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - Config.parse(string) -> OpenSSL::Config
    # -->
    # Parses a given *string* as a blob that contains configuration for OpenSSL.
    #
    def self.parse: (String string) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - Config.parse_config(io) -> hash
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - config[section] -> hash
    # -->
    # 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')
    #       #=> #<OpenSSL::Config sections=["default"]>
    #     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]

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/config.rb
    #   - []=(section, pairs)
    # -->
    # *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
    #       #=> #<OpenSSL::Config sections=[]>
    #     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 ]]

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/config.rb
    #   - add_value(section, key, value)
    # -->
    # *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')
    #       #=> #<OpenSSL::Config sections=["default"]>
    #     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

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - config.each { |section, key, value| }
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - config.get_value(section, key) -> string
    # -->
    # Gets the value of *key* from the given *section*.
    #
    # Given the following configurating file being loaded:
    #
    #     config = OpenSSL::Config.load('foo.cnf')
    #       #=> #<OpenSSL::Config sections=["default"]>
    #     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?

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - config.inspect -> string
    # -->
    # String representation of this configuration object, including the class name
    # and its sections.
    #
    def inspect: () -> String

    def section: (String name) -> Hash[String, String]

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - config.sections -> array of string
    # -->
    # Get the names of all sections in the current configuration.
    #
    def sections: () -> Array[String]

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - config.to_s -> string
    # -->
    # Gets the parsable form of the current configuration.
    #
    # Given the following configuration being created:
    #
    #     config = OpenSSL::Config.new
    #       #=> #<OpenSSL::Config sections=[]>
    #     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)
    #       #=> #<OpenSSL::Config sections=["default"]>
    #     puts new_config
    #       #=> [ default ]
    #           foo=bar
    #           baz=buz
    #
    def to_s: () -> String

    private

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - Config.new(filename) -> OpenSSL::Config
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_config.c
    #   - initialize_copy(p1)
    # -->
    #
    def initialize_copy: (instance other) -> void

    # <!-- rdoc-file=ext/openssl/ossl_config.c -->
    # The default system configuration file for OpenSSL.
    #
    DEFAULT_CONFIG_FILE: String
  end

  # <!-- rdoc-file=ext/openssl/ossl_config.c -->
  # General error for openssl library configuration files. Including formatting,
  # parsing errors, etc.
  #
  class ConfigError < OpenSSL::OpenSSLError
  end

  # <!-- rdoc-file=ext/openssl/ossl_digest.c -->
  # 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
    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/digest.rb
    #   - digest(name, data)
    # -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_digest.c -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - digest.block_length -> integer
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - digest.digest_length -> integer
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - digest.name -> string
    # -->
    # Returns the sn of this Digest algorithm.
    #
    # ### Example
    #     digest = OpenSSL::Digest.new('SHA512')
    #     puts digest.name # => SHA512
    #
    def name: () -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - digest.reset -> self
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - digest.update(string) -> aString
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - digest.finish -> aString
    # -->
    #
    def finish: (*untyped) -> untyped

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - Digest.new(string [, data]) -> Digest
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_digest.c
    #   - initialize_copy(p1)
    # -->
    #
    def initialize_copy: (instance) -> void

    class Digest < OpenSSL::Digest
    end

    # <!-- rdoc-file=ext/openssl/ossl_digest.c -->
    # 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

  # <!-- rdoc-file=ext/openssl/ossl_engine.c -->
  # This class is the access to openssl's ENGINE cryptographic module
  # implementation.
  #
  # See also, https://www.openssl.org/docs/crypto/engine.html
  #
  class Engine
    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - OpenSSL::Engine.by_id(name) -> engine
    # -->
    # Fetches the engine as specified by the *id* String.
    #
    #     OpenSSL::Engine.by_id("openssl")
    #      => #<OpenSSL::Engine id="openssl" name="Software engine support">
    #
    # See OpenSSL::Engine.engines for the currently loaded engines.
    #
    def self.by_id: (String name) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - OpenSSL::Engine.cleanup
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - OpenSSL::Engine.engines -> [engine, ...]
    # -->
    # Returns an array of currently loaded engines.
    #
    def self.engines: () -> Array[instance]

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - OpenSSL::Engine.load(name = nil)
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.cipher(name) -> OpenSSL::Cipher
    # -->
    # 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")
    #      => #<OpenSSL::Engine id="openssl" name="Software engine support">
    #     e.cipher("RC4")
    #      => #<OpenSSL::Cipher:0x007fc5cacc3048>
    #
    def cipher: (String cipher) -> Cipher

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.cmds -> [["name", "description", "flags"], ...]
    # -->
    # Returns an array of command definitions for the current engine
    #
    def cmds: () -> Array[[ String, String, String ]]

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.ctrl_cmd(command, value = nil) -> engine
    # -->
    # Sends the given *command* to this engine.
    #
    # Raises an EngineError if the command fails.
    #
    def ctrl_cmd: (String cmd, ?String value) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.digest(name) -> OpenSSL::Digest
    # -->
    # Returns a new instance of OpenSSL::Digest by *name*.
    #
    # Will raise an EngineError if the digest is unavailable.
    #
    #     e = OpenSSL::Engine.by_id("openssl")
    #       #=> #<OpenSSL::Engine id="openssl" name="Software engine support">
    #     e.digest("SHA1")
    #       #=> #<OpenSSL::Digest: da39a3ee5e6b4b0d3255bfef95601890afd80709>
    #     e.digest("zomg")
    #       #=> OpenSSL::Engine::EngineError: no such digest `zomg'
    #
    def digest: (String digest) -> Digest

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.finish -> nil
    # -->
    # Releases all internal structural references for this engine.
    #
    # May raise an EngineError if the engine is unavailable
    #
    def finish: () -> nil

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.id -> string
    # -->
    # Gets the id for this engine.
    #
    #     OpenSSL::Engine.load
    #     OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
    #     OpenSSL::Engine.engines.first.id
    #       #=> "rsax"
    #
    def id: () -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.inspect -> string
    # -->
    # Pretty prints this engine.
    #
    def inspect: () -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.load_private_key(id = nil, data = nil) -> OpenSSL::PKey
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.load_public_key(id = nil, data = nil) -> OpenSSL::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

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.name -> string
    # -->
    # Get the descriptive name for this engine.
    #
    #     OpenSSL::Engine.load
    #     OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
    #     OpenSSL::Engine.engines.first.name
    #       #=> "RSAX engine support"
    #
    def name: () -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_engine.c
    #   - engine.set_default(flag)
    # -->
    # 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 <openssl/engine.h>
    #
    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

    # <!-- rdoc-file=ext/openssl/ossl_engine.c -->
    # This is the generic exception for OpenSSL::Engine related errors
    #
    class EngineError < OpenSSL::OpenSSLError
    end
  end

  # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
  # 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

  # <!-- rdoc-file=ext/openssl/ossl_hmac.c -->
  # 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
    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/hmac.rb
    #   - HMAC.digest(digest, key, data) -> aString
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/hmac.rb
    #   - HMAC.hexdigest(digest, key, data) -> aString
    # -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_hmac.c -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/hmac.rb
    #   - ==(other)
    # -->
    # Securely compare with another HMAC instance in constant time.
    #
    def ==: (instance other) -> bool

    # <!--
    #   rdoc-file=ext/openssl/ossl_hmac.c
    #   - hmac.digest -> string
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_hmac.c
    #   - hmac.hexdigest -> string
    # -->
    # Returns the authentication code an instance represents as a hex-encoded
    # string.
    #
    def hexdigest: () -> String

    # <!-- rdoc-file=ext/openssl/lib/openssl/hmac.rb -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_hmac.c
    #   - hmac.reset -> self
    # -->
    # 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

    # <!-- rdoc-file=ext/openssl/lib/openssl/hmac.rb -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_hmac.c
    #   - hmac.update(string) -> self
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_hmac.c
    #   - HMAC.new(key, digest) -> hmac
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_hmac.c
    #   - initialize_copy(p1)
    # -->
    #
    def initialize_copy: (instance) -> void
  end

  # <!-- rdoc-file=ext/openssl/ossl_hmac.c -->
  # 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

  # <!-- rdoc-file=ext/openssl/ossl_kdf.c -->
  # 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
    # <!--
    #   rdoc-file=ext/openssl/ossl_kdf.c
    #   - KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_kdf.c
    #   - KDF.pbkdf2_hmac(pass, salt:, iterations:, length:, hash:) -> aString
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_kdf.c
    #   - KDF.scrypt(pass, salt:, N:, r:, p:, length:) -> aString
    # -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_kdf.c -->
    # Generic exception class raised if an error occurs in OpenSSL::KDF module.
    #
    class KDFError < OpenSSL::OpenSSLError
    end
  end

  module Marshal
    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/marshal.rb
    #   - included(base)
    # -->
    #
    def self.included: (untyped base) -> untyped

    public

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/marshal.rb
    #   - _dump(_level)
    # -->
    #
    def _dump: (untyped _level) -> untyped

    module ClassMethods
      public

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/marshal.rb
      #   - _load(string)
      # -->
      #
      def _load: (untyped string) -> untyped
    end
  end

  # <!-- rdoc-file=ext/openssl/ossl_ns_spki.c -->
  # 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
    # <!-- rdoc-file=ext/openssl/ossl_ns_spki.c -->
    # 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
    # <keygen> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.challenge => string
      # -->
      # Returns the challenge string associated with this SPKI.
      #
      def challenge: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.challenge = str => 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.public_key => pkey
      # -->
      # Returns the public key associated with the SPKI, an instance of OpenSSL::PKey.
      #
      def public_key: () -> PKey::PKey

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.public_key = pub => 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.sign(key, digest) => spki
      # -->
      # ### 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.to_der => DER-encoded string
      # -->
      # Returns the DER encoding of this SPKI.
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.to_pem => PEM-encoded string
      # -->
      # Returns the PEM encoding of this SPKI.
      #
      def to_pem: () -> String

      # <!-- rdoc-file=ext/openssl/ossl_ns_spki.c -->
      # Returns the PEM encoding of this SPKI.
      #
      alias to_s to_pem

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.to_text => string
      # -->
      # Returns a textual representation of this SPKI, useful for debugging purposes.
      #
      def to_text: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - spki.verify(key) => boolean
      # -->
      # ### 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ns_spki.c
      #   - SPKI.new([request]) => spki
      # -->
      # ### Parameters
      # *   *request* - optional raw request, either in PEM or DER format.
      #
      def initialize: (?String request) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_ns_spki.c -->
    # 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

  # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
  # 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
    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # (This flag is not used by OpenSSL 1.0.1g)
    #
    NOCASIGN: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not include certificates in the response
    #
    NOCERTS: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not verify the certificate chain on the response
    #
    NOCHAIN: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not make additional signing certificate checks
    #
    NOCHECKS: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # (This flag is not used by OpenSSL 1.0.1g)
    #
    NODELEGATED: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not check trust
    #
    NOEXPLICIT: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not search certificates contained in the response for a signer
    #
    NOINTERN: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not check the signature on the response
    #
    NOSIGS: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not include producedAt time in response
    #
    NOTIME: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not verify the response at all
    #
    NOVERIFY: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Identify the response by signing the certificate key ID
    #
    RESPID_KEY: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Internal error in issuer
    #
    RESPONSE_STATUS_INTERNALERROR: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Illegal confirmation request
    #
    RESPONSE_STATUS_MALFORMEDREQUEST: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # You must sign the request and resubmit
    #
    RESPONSE_STATUS_SIGREQUIRED: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Response has valid confirmations
    #
    RESPONSE_STATUS_SUCCESSFUL: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Try again later
    #
    RESPONSE_STATUS_TRYLATER: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Your request is unauthorized.
    #
    RESPONSE_STATUS_UNAUTHORIZED: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate subject's name or other information changed
    #
    REVOKED_STATUS_AFFILIATIONCHANGED: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # This CA certificate was revoked due to a key compromise
    #
    REVOKED_STATUS_CACOMPROMISE: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate is on hold
    #
    REVOKED_STATUS_CERTIFICATEHOLD: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate is no longer needed
    #
    REVOKED_STATUS_CESSATIONOFOPERATION: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate was revoked due to a key compromise
    #
    REVOKED_STATUS_KEYCOMPROMISE: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate was revoked for an unknown reason
    #
    REVOKED_STATUS_NOSTATUS: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate was previously on hold and should now be removed from the CRL
    #
    REVOKED_STATUS_REMOVEFROMCRL: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate was superseded by a new certificate
    #
    REVOKED_STATUS_SUPERSEDED: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The certificate was revoked for an unspecified reason
    #
    REVOKED_STATUS_UNSPECIFIED: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Do not verify additional certificates
    #
    TRUSTOTHER: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Indicates the certificate has been revoked either permanently or temporarily
    # (on hold).
    #
    V_CERTSTATUS_REVOKED: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # Indicates the responder does not know about the certificate being requested.
    #
    V_CERTSTATUS_UNKNOWN: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The responder ID is based on the public key.
    #
    V_RESPID_KEY: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # The responder ID is based on the key name.
    #
    V_RESPID_NAME: Integer

    type ocsp_status = Integer

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.add_nonce(nonce = nil)
      # -->
      # Adds *nonce* to this response.  If no nonce was provided a random nonce will
      # be added.
      #
      def add_nonce: (?String nonce) -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) -> basic_response
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.copy_nonce(request) -> Integer
      # -->
      # Copies the nonce from *request* into this response.  Returns 1 on success and
      # 0 on failure.
      #
      def copy_nonce: (Request request) -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.find_response(certificate_id) -> SingleResponse | nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.responses -> Array of SingleResponse
      # -->
      # Returns an Array of SingleResponse for this BasicResponse.
      #
      def responses: () -> Array[SingleResponse]

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.status -> statuses
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.to_der -> String
      # -->
      # Encodes this basic response into a DER-encoded string.
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - basic_response.verify(certificates, store, flags = 0) -> true or false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - OpenSSL::OCSP::BasicResponse.new(der_string = nil) -> basic_response
      # -->
      # Creates a new BasicResponse. If *der_string* is given, decodes *der_string* as
      # DER.
      #
      def initialize: (?String der) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so that a
    # status check can be performed.
    #
    class CertificateId
      public

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - certificate_id.cmp(other) -> true or false
      # -->
      # Compares this certificate id with *other* and returns `true` if they are the
      # same.
      #
      def cmp: (instance other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - certificate_id.cmp_issuer(other) -> true or false
      # -->
      # Compares this certificate id's issuer with *other* and returns `true` if they
      # are the same.
      #
      def cmp_issuer: (instance other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - certificate_id.hash_algorithm -> String
      # -->
      # Returns the ln (long name) of the hash algorithm used to generate the
      # issuerNameHash and the issuerKeyHash values.
      #
      def hash_algorithm: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - certificate_id.issuer_key_hash -> String
      # -->
      # Returns the issuerKeyHash of this certificate ID, the hash of the issuer's
      # public key.
      #
      def issuer_key_hash: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - certificate_id.issuer_name_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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - certificate_id.serial -> Integer
      # -->
      # Returns the serial number of the certificate for which status is being
      # requested.
      #
      def serial: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - certificate_id.to_der -> String
      # -->
      # Encodes this certificate identifier into a DER-encoded string.
      #
      def to_der: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id
      #   - OpenSSL::OCSP::CertificateId.new(der_string)                    -> certificate_id
      #   - OpenSSL::OCSP::CertificateId.new(obj)                           -> certificate_id
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # OCSP error class.
    #
    class OCSPError < OpenSSL::OpenSSLError
    end

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - request.add_certid(certificate_id) -> request
      # -->
      # Adds *certificate_id* to the request.
      #
      def add_certid: (CertificateId certificate_id) -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - request.add_nonce(nonce = nil) -> request
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - request.certid -> [certificate_id, ...]
      # -->
      # Returns all certificate IDs in this request.
      #
      def certid: () -> Array[CertificateId]

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - request.check_nonce(response) -> result
      # -->
      # 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)

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - request.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - request.signed? -> true or false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - to_der()
      # -->
      # Returns this request as a DER-encoded string
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - request.verify(certificates, store, flags = 0) -> true or false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - OpenSSL::OCSP::Request.new              -> request
      #   - OpenSSL::OCSP::Request.new(request_der) -> request
      # -->
      # Creates a new OpenSSL::OCSP::Request.  The request may be created empty or
      # from a *request_der* string.
      #
      def initialize: (?String der) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # An OpenSSL::OCSP::Response contains the status of a certificate check which is
    # created from an OpenSSL::OCSP::Request.
    #
    class Response
      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - OpenSSL::OCSP::Response.create(status, basic_response = nil) -> response
      # -->
      # Creates an OpenSSL::OCSP::Response from *status* and *basic_response*.
      #
      def self.create: (Integer status, ?BasicResponse response) -> instance

      public

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - response.basic
      # -->
      # Returns a BasicResponse for this response
      #
      def basic: () -> BasicResponse?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - response.status -> Integer
      # -->
      # Returns the status of the response.
      #
      def status: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - response.status_string -> String
      # -->
      # Returns a status string for the response.
      #
      def status_string: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - response.to_der -> String
      # -->
      # Returns this response as a DER-encoded string.
      #
      def to_der: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - OpenSSL::OCSP::Response.new               -> response
      #   - OpenSSL::OCSP::Response.new(response_der) -> response
      # -->
      # Creates a new OpenSSL::OCSP::Response.  The response may be created empty or
      # from a *response_der* string.
      #
      def initialize: (?String der) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_ocsp.c -->
    # An OpenSSL::OCSP::SingleResponse represents an OCSP SingleResponse structure,
    # which contains the basic information of the status of the certificate.
    #
    class SingleResponse
      public

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.cert_status -> Integer
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.certid -> CertificateId
      # -->
      # Returns the CertificateId for which this SingleResponse is.
      #
      def certid: () -> CertificateId

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.check_validity(nsec = 0, maxsec = -1) -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.extensions -> Array of X509::Extension
      # -->
      #
      def extensions: () -> Array[X509::Certificate]

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.next_update -> Time | nil
      # -->
      #
      def next_update: () -> Time?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.revocation_reason -> Integer | nil
      # -->
      #
      def revocation_reason: () -> Integer?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.revocation_time -> Time | nil
      # -->
      #
      def revocation_time: () -> Time?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.this_update -> Time
      # -->
      #
      def this_update: () -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - single_response.to_der -> String
      # -->
      # Encodes this SingleResponse into a DER-encoded string.
      #
      def to_der: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - OpenSSL::OCSP::SingleResponse.new(der_string) -> SingleResponse
      # -->
      # Creates a new SingleResponse from *der_string*.
      #
      def initialize: (String der) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_ocsp.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end
  end

  # <!-- rdoc-file=ext/openssl/ossl.c -->
  # Generic error, common for all classes under OpenSSL module
  #
  class OpenSSLError < StandardError
  end

  # <!-- rdoc-file=ext/openssl/ossl_pkcs12.c -->
  # Defines a file format commonly used to store private keys with accompanying
  # public key certificates, protected with a password-based symmetric key.
  #
  class PKCS12
    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs12.c
    #   - PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
    # -->
    # ### 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs12.c
    #   - to_der()
    # -->
    #
    def to_der: () -> String

    private

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs12.c
    #   - PKCS12.new -> pkcs12
    #   - PKCS12.new(str) -> pkcs12
    #   - PKCS12.new(str, pass) -> pkcs12
    # -->
    # ### Parameters
    # *   *str* - Must be a DER encoded PKCS12 string.
    # *   *pass* - string
    #
    def initialize: (?String der, ?String pass) -> void

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs12.c
    #   - initialize_copy(p1)
    # -->
    #
    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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/pkcs5.rb
    #   - pbkdf2_hmac(pass, salt, iter, keylen, digest)
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/pkcs5.rb
    #   - pbkdf2_hmac_sha1(pass, salt, iter, keylen)
    # -->
    #
    def pbkdf2_hmac_sha1: (untyped pass, untyped salt, untyped iter, untyped keylen) -> untyped
  end

  class PKCS7
    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
    # -->
    #
    def self.encrypt: (X509::Certificate certs, String data, ?Cipher cipher, ?Integer flags) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - PKCS7.read_smime(string) => pkcs7
    # -->
    #
    def self.read_smime: (String) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7
    # -->
    #
    def self.sign: (X509::Certificate certs, PKey::PKey key, String data, ?OpenSSL::Cipher cipher, ?Integer flags) -> instance

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
    # -->
    #
    def self.write_smime: (instance pkcs7, ?String data, ?Integer flags) -> String

    public

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - add_certificate(p1)
    # -->
    #
    def add_certificate: (X509::Certificate cert) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - add_crl(p1)
    # -->
    #
    def add_crl: (X509::CRL crl) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - add_data(p1)
    # -->
    #
    def add_data: (String data) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - add_recipient(p1)
    # -->
    #
    def add_recipient: (RecipientInfo recipient) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - add_signer(p1)
    # -->
    #
    def add_signer: (SignerInfo signer) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - certificates()
    # -->
    #
    def certificates: () -> Array[X509::Certificate]?

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - certificates=(p1)
    # -->
    #
    def certificates=: (Array[X509::Certificate]) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - cipher=(p1)
    # -->
    #
    def cipher=: (Cipher cipher) -> self

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - crls()
    # -->
    #
    def crls: () -> Array[X509::CRL]?

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - crls=(p1)
    # -->
    #
    def crls=: (Array[X509::CRL]) -> self

    def data: () -> String?

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - data=(p1)
    # -->
    #
    alias data= add_data

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - decrypt(p1, p2 = v2, p3 = v3)
    # -->
    #
    def decrypt: (PKey::PKey p1, ?PKey::PKey p2, ?PKey::PKey p3) -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - detached()
    # -->
    #
    def detached: () -> bool

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - detached=(p1)
    # -->
    #
    def detached=: [U] (boolish) -> U

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - detached?()
    # -->
    #
    def detached?: () -> bool

    def error_string: () -> String?

    def error_string=: (String) -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - recipients()
    # -->
    #
    def recipients: () -> Array[RecipientInfo]

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - signers()
    # -->
    #
    def signers: () -> Array[SignerInfo]

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - to_der()
    # -->
    #
    def to_der: () -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - to_pem()
    # -->
    #
    def to_pem: () -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - to_s()
    # -->
    #
    alias to_s to_pem

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - pkcs7.type => string or nil
    # -->
    #
    def type: () -> String?

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - pkcs7.type = type => type
    # -->
    #
    def type=: (String) -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - verify(p1, p2, p3 = v3, p4 = v4)
    # -->
    #
    def verify: (PKey::PKey p1, PKey::PKey p2, ?PKey::PKey p3, ?PKey::PKey p4) -> bool

    private

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - PKCS7.new => pkcs7
    #   - PKCS7.new(string) => pkcs7
    # -->
    # Many methods in this class aren't documented.
    #
    def initialize: (?String der) -> void

    # <!--
    #   rdoc-file=ext/openssl/ossl_pkcs7.c
    #   - initialize_copy(p1)
    # -->
    #
    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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - enc_key()
      # -->
      #
      def enc_key: () -> PKey::PKey

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - issuer()
      # -->
      #
      def issuer: () -> X509::Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - serial()
      # -->
      #
      def serial: () -> Integer

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - new(p1)
      # -->
      #
      def initialize: (X509::Certificate certificate) -> void
    end

    class SignerInfo
      public

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - issuer()
      # -->
      #
      def issuer: () -> X509::Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - serial()
      # -->
      #
      def serial: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - signed_time()
      # -->
      #
      def signed_time: () -> Time?

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkcs7.c
      #   - new(p1, p2, p3)
      # -->
      #
      def initialize: (X509::Certificate certificate, PKey::PKey key, Digest digest) -> void
    end
  end

  # <!-- rdoc-file=ext/openssl/ossl_pkey.c -->
  # ## 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
    # <!--
    #   rdoc-file=ext/openssl/ossl_pkey.c
    #   - OpenSSL::PKey.read(string [, pwd ]) -> PKey
    #   - OpenSSL::PKey.read(io [, pwd ]) -> 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

    # <!-- rdoc-file=ext/openssl/ossl_pkey_dh.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - DH.generate(size, generator = 2) -> dh
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - dh.compute_key(pub_bn) -> string
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.export -> aString
      #   - dh.to_pem -> aString
      #   - dh.to_s -> aString
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - dh.generate_key! -> self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.params -> hash
      # -->
      # 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]

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.params_ok? -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.private? -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.public? -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - dh.public_key -> dhnew
      # -->
      # 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 #=> #<OpenSSL::BN 1288347...>
      #     dhcopy = dh1.public_key
      #     p dhcopy.priv_key #=> nil
      #
      def public_key: () -> instance

      def q: () -> BN

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.set_key(pub_key, priv_key) -> self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.set_pqg(p, q, g) -> self
      # -->
      # Sets *p*, *q*, *g* to the DH instance.
      #
      def set_pqg: (bn p, bn q, bn g) -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.to_der -> aString
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_pkey_dh.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_pkey_dh.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - dh.to_text -> aString
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - DH.new -> dh
      #   - DH.new(string) -> dh
      #   - DH.new(size [, generator]) -> dh
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dh.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_pkey_dh.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_pkey_dsa.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - DSA.generate(size) -> dsa
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.export([cipher, password]) -> aString
      #   - dsa.to_pem([cipher, password]) -> aString
      #   - dsa.to_s([cipher, password]) -> aString
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.params -> hash
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.private? -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.public? -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - dsa.public_key -> dsanew
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.set_key(pub_key, priv_key) -> self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.set_pqg(p, q, g) -> self
      # -->
      # Sets *p*, *q*, *g* to the DSA instance.
      #
      def set_pqg: (bn p, bn q, bn g) -> self

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - dsa.syssign(string) -> string
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - dsa.sysverify(digest, sig) -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.to_der -> aString
      # -->
      # Encodes this DSA to its DER encoding.
      #
      def to_der: () -> String

      # <!-- rdoc-file=ext/openssl/ossl_pkey_dsa.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_pkey_dsa.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - dsa.to_text -> aString
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - DSA.new -> dsa
      #   - DSA.new(string [, pass]) -> dsa
      #   - DSA.new(size) -> dsa
      # -->
      # 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)
      #     #=> #<OpenSSL::PKey::DSA:0x000055a8d6025bf0 oid=DSA>
      #
      #     p OpenSSL::PKey::DSA.new(File.read('dsa.pem'))
      #     #=> #<OpenSSL::PKey::DSA:0x000055555d6b8110 oid=DSA>
      #
      #     p OpenSSL::PKey::DSA.new(File.read('dsa.pem'), 'mypassword')
      #     #=> #<OpenSSL::PKey::DSA:0x0000556f973c40b8 oid=DSA>
      #
      def initialize: (String pem, ?String pass) -> void
                    | (?Integer size) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_dsa.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_pkey_dsa.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_pkey_ec.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - EC.builtin_curves => [[sn, comment], ...]
      # -->
      # 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 ]]

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - EC.generate(ec_group) -> ec
      #   - EC.generate(string) -> ec
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.check_key   => true
      # -->
      # Raises an exception if the key is invalid.
      #
      # See also the man page EVP_PKEY_public_check(3).
      #
      def check_key: () -> true

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - ec.dh_compute_key(pubkey) -> string
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - key.dsa_sign_asn1(data) -> 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - key.dsa_verify_asn1(data, sig) -> true | false
      # -->
      # **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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.export([cipher, pass_phrase]) => String
      #   - key.to_pem([cipher, pass_phrase]) => 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.
      #
      def export: (String cipher, String password) -> String
                | () -> String

      # <!-- rdoc-file=ext/openssl/ossl_pkey_ec.c -->
      # 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 # => #<OpenSSL::BN XXXXXX>
      #
      alias generate_key generate_key!

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.generate_key!   => self
      # -->
      # 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 # => #<OpenSSL::BN XXXXXX>
      #
      def generate_key!: () -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.group   => group
      # -->
      # Returns the EC::Group that the key is associated with. Modifying the returned
      # group does not affect *key*.
      #
      def group: () -> Group?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.private? => true or false
      # -->
      # Returns whether this EC instance has a private key. The private key (BN) can
      # be retrieved with EC#private_key.
      #
      def private?: () -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.private_key   => OpenSSL::BN
      # -->
      # See the OpenSSL documentation for EC_KEY_get0_private_key()
      #
      def private_key: () -> BN?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.private_key = openssl_bn
      # -->
      # See the OpenSSL documentation for EC_KEY_set_private_key()
      #
      def private_key=: (bn priv_key) -> self

      # <!-- rdoc-file=ext/openssl/ossl_pkey_ec.c -->
      # Returns whether this EC instance has a private key. The private key (BN) can
      # be retrieved with EC#private_key.
      #
      alias private_key? private?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.public? => true or false
      # -->
      # Returns whether this EC instance has a public key. The public key (EC::Point)
      # can be retrieved with EC#public_key.
      #
      def public?: () -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.public_key   => OpenSSL::PKey::EC::Point
      # -->
      # See the OpenSSL documentation for EC_KEY_get0_public_key()
      #
      def public_key: () -> Point?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.public_key = ec_point
      # -->
      # See the OpenSSL documentation for EC_KEY_set_public_key()
      #
      def public_key=: (bn priv_key) -> self

      # <!-- rdoc-file=ext/openssl/ossl_pkey_ec.c -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.to_der   => String
      # -->
      # See the OpenSSL documentation for i2d_ECPrivateKey_bio()
      #
      def to_der: () -> String

      # <!-- rdoc-file=ext/openssl/ossl_pkey_ec.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - key.to_text   => String
      # -->
      # See the OpenSSL documentation for EC_KEY_print()
      #
      def to_text: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - OpenSSL::PKey::EC.new
      #   - OpenSSL::PKey::EC.new(ec_key)
      #   - OpenSSL::PKey::EC.new(ec_group)
      #   - OpenSSL::PKey::EC.new("secp112r1")
      #   - OpenSSL::PKey::EC.new(pem_string [, pwd])
      #   - OpenSSL::PKey::EC.new(der_string)
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_ec.c
      #   - initialize_copy(p1)
      # -->
      #
      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

        # <!-- rdoc-file=ext/openssl/ossl_pkey_ec.c -->
        # Returns `true` if the two groups use the same curve and have the same
        # parameters, `false` otherwise.
        #
        alias == eql?

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.asn1_flag -> Integer
        # -->
        # Returns the flags set on the group.
        #
        # See also #asn1_flag=.
        #
        def asn1_flag: () -> Integer

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.asn1_flag = flags
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.get_cofactor   => cofactor_bn
        # -->
        # Returns the cofactor of the group.
        #
        # See the OpenSSL documentation for EC_GROUP_get_cofactor()
        #
        def cofactor: () -> BN

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.curve_name  => String
        # -->
        # Returns the curve name (sn).
        #
        # See the OpenSSL documentation for EC_GROUP_get_curve_name()
        #
        def curve_name: () -> String

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.degree   => integer
        # -->
        # See the OpenSSL documentation for EC_GROUP_get_degree()
        #
        def degree: () -> Integer

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group1.eql?(group2)   => true | false
        #   - group1 == group2   => true | false
        # -->
        # Returns `true` if the two groups use the same curve and have the same
        # parameters, `false` otherwise.
        #
        def eql?: (instance other) -> bool

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.generator   => ec_point
        # -->
        # Returns the generator of the group.
        #
        # See the OpenSSL documentation for EC_GROUP_get0_generator()
        #
        def generator: () -> Point?

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.get_order   => order_bn
        # -->
        # Returns the order of the group.
        #
        # See the OpenSSL documentation for EC_GROUP_get_order()
        #
        def order: () -> BN

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.point_conversion_form -> Symbol
        # -->
        # Returns the form how EC::Point data is encoded as ASN.1.
        #
        # See also #point_conversion_form=.
        #
        def point_conversion_form: () -> point_conversion_format

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.point_conversion_form = form
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.seed   => String or nil
        # -->
        # See the OpenSSL documentation for EC_GROUP_get0_seed()
        #
        def seed: () -> String?

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.seed = seed  => seed
        # -->
        # See the OpenSSL documentation for EC_GROUP_set_seed()
        #
        def seed=: (String seed) -> String

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.set_generator(generator, order, cofactor)   => self
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.to_der   => String
        # -->
        # See the OpenSSL documentation for i2d_ECPKParameters_bio()
        #
        def to_der: () -> String

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.to_pem   => String
        # -->
        # See the OpenSSL documentation for PEM_write_bio_ECPKParameters()
        #
        def to_pem: () -> String

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - group.to_text   => String
        # -->
        # See the OpenSSL documentation for ECPKParameters_print()
        #
        def to_text: () -> String

        private

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - OpenSSL::PKey::EC::Group.new(ec_group)
        #   - OpenSSL::PKey::EC::Group.new(pem_or_der_encoded)
        #   - OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b)
        #   - OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b)
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - initialize_copy(p1)
        # -->
        #
        def initialize_copy: (instance) -> void

        class Error < OpenSSL::OpenSSLError
        end
      end

      class Point
        public

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - ==(p1)
        # -->
        #
        alias == eql?

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.add(point) => point
        # -->
        # Performs elliptic curve point addition.
        #
        def add: (instance point) -> instance

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point1.eql?(point2) => true | false
        #   - point1 == point2 => true | false
        # -->
        #
        def eql?: (instance other) -> bool

        def group: () -> Group

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.infinity? => true | false
        # -->
        #
        def infinity?: () -> bool

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.invert! => self
        # -->
        #
        def invert!: () -> self

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.make_affine! => self
        # -->
        # This method is deprecated and should not be used. This is a no-op.
        #
        def make_affine!: () -> self

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.mul(bn1 [, bn2]) => point
        #   - point.mul(bns, points [, bn2]) => point
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.on_curve? => true | false
        # -->
        #
        def on_curve?: () -> bool

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.set_to_infinity! => self
        # -->
        #
        def set_to_infinity!: () -> self

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
        #   - point.to_bn([conversion_form]) -> OpenSSL::BN
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - point.to_octet_string(conversion_form) -> String
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - OpenSSL::PKey::EC::Point.new(point)
        #   - OpenSSL::PKey::EC::Point.new(group [, encoded_point])
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/ossl_pkey_ec.c
        #   - initialize_copy(p1)
        # -->
        #
        def initialize_copy: (instance) -> void

        class Error < OpenSSL::OpenSSLError
        end
      end
    end

    class ECError < OpenSSL::PKey::PKeyError
    end

    # <!-- rdoc-file=ext/openssl/ossl_pkey.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.inspect -> string
      # -->
      # Returns a string describing the PKey object.
      #
      def inspect: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.oid -> string
      # -->
      # Returns the short name of the OID associated with *pkey*.
      #
      def oid: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.private_to_der                   -> string
      #   - pkey.private_to_der(cipher, password) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.private_to_pem                   -> string
      #   - pkey.private_to_pem(cipher, password) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.public_to_der -> string
      # -->
      # Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format.
      #
      def public_to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.public_to_pem -> string
      # -->
      # Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format.
      #
      def public_to_pem: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.sign(digest, data [, options]) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - pkey.verify(digest, signature, data [, options]) -> true or false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey.c
      #   - PKeyClass.new -> self
      # -->
      # Because PKey is an abstract class, actually calling this method explicitly
      # will raise a NotImplementedError.
      #
      def initialize: () -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_pkey.c -->
    # Raised when errors occur during PKey#sign or PKey#verify.
    #
    class PKeyError < OpenSSL::OpenSSLError
    end

    # <!-- rdoc-file=ext/openssl/ossl_pkey_rsa.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - RSA.generate(size, exponent = 65537) -> RSA
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.export([cipher, pass_phrase]) => PEM-format String
      #   - rsa.to_pem([cipher, pass_phrase]) => PEM-format String
      #   - rsa.to_s([cipher, pass_phrase]) => PEM-format 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.
      #
      def export: (String cipher, String password) -> String
                | () -> String

      def iqmp: () -> BN?

      def n: () -> BN?

      def p: () -> BN?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.params => hash
      # -->
      # 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]

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.private? => true | false
      # -->
      # Does this keypair contain a private key?
      #
      def private?: () -> bool

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - rsa.private_decrypt(string)          -> String
      #   - rsa.private_decrypt(string, padding) -> String
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - rsa.private_encrypt(string)          -> String
      #   - rsa.private_encrypt(string, 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.public? => true
      # -->
      # The return value is always `true` since every private key is also a public
      # key.
      #
      def public?: () -> bool

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - rsa.public_decrypt(string)          -> String
      #   - rsa.public_decrypt(string, padding) -> String
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - rsa.public_encrypt(string)          -> String
      #   - rsa.public_encrypt(string, 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/pkey.rb
      #   - rsa.public_key -> rsanew
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.set_crt_params(dmp1, dmq1, iqmp) -> self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.set_factors(p, q) -> self
      # -->
      # Sets *p*, *q* for the RSA instance.
      #
      def set_factors: (bn p, bn q) -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.set_key(n, e, d) -> self
      # -->
      # Sets *n*, *e*, *d* for the RSA instance.
      #
      def set_key: (bn n, bn e, bn d) -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.to_der => DER-format String
      # -->
      # Outputs this keypair in DER encoding.
      #
      def to_der: () -> String

      # <!-- rdoc-file=ext/openssl/ossl_pkey_rsa.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_pkey_rsa.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.to_text => String
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - rsa.verify_pss(digest, signature, data, salt_length:, mgf1_hash:) -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - RSA.new -> rsa
      #   - RSA.new(encoded_key [, passphrase]) -> rsa
      #   - RSA.new(encoded_key) { passphrase } -> rsa
      #   - RSA.new(size [, exponent]) -> rsa
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_pkey_rsa.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void

      NO_PADDING: Integer

      PKCS1_OAEP_PADDING: Integer

      PKCS1_PADDING: Integer

      SSLV23_PADDING: Integer
    end

    # <!-- rdoc-file=ext/openssl/ossl_pkey_rsa.c -->
    # 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
    # <!--
    #   rdoc-file=ext/openssl/ossl_rand.c
    #   - load_random_file(filename) -> true
    # -->
    # Reads bytes from *filename* and adds them to the PRNG.
    #
    def self.load_random_file: (String filename) -> true

    # <!--
    #   rdoc-file=ext/openssl/ossl_rand.c
    #   - add(str, entropy) -> self
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_rand.c
    #   - random_bytes(length) -> string
    # -->
    # 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

    # <!--
    #   rdoc-file=ext/openssl/ossl_rand.c
    #   - seed(str) -> str
    # -->
    # ::seed is equivalent to ::add where *entropy* is length of *str*.
    #
    def self.seed: (String seed) -> String

    # <!--
    #   rdoc-file=ext/openssl/ossl_rand.c
    #   - status? => true | false
    # -->
    # Return `true` if the PRNG has been seeded with enough data, `false` otherwise.
    #
    def self.status?: () -> bool

    # <!--
    #   rdoc-file=ext/openssl/ossl_rand.c
    #   - write_random_file(filename) -> true
    # -->
    # 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

  # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
  # 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
    # <!--
    #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
    #   - verify_certificate_identity(cert, hostname)
    # -->
    #
    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

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.0.1k and 1.0.2.
    #
    OP_EPHEMERAL_RSA: Integer

    OP_LEGACY_SERVER_CONNECT: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_MICROSOFT_BIG_SSLV3_BUFFER: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_MICROSOFT_SESS_ID_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 0.9.7h and 0.9.8b.
    #
    OP_MSIE_SSLV2_RSA_PADDING: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_NETSCAPE_CA_DN_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_NETSCAPE_CHALLENGE_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.0.1.
    #
    OP_PKCS1_CHECK_1: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.0.1.
    #
    OP_PKCS1_CHECK_2: Integer

    OP_SAFARI_ECDHE_ECDSA_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_SINGLE_DH_USE: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_SINGLE_ECDH_USE: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_SSLEAY_080_CLIENT_DH_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.0.1h and 1.0.2.
    #
    OP_SSLREF2_REUSE_CERT_TYPE_BUG: Integer

    OP_TLSEXT_PADDING: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_TLS_BLOCK_PADDING_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # Deprecated in OpenSSL 1.1.0.
    #
    OP_TLS_D5_BUG: Integer

    OP_TLS_ROLLBACK_BUG: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # SSL 2.0
    #
    SSL2_VERSION: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # SSL 3.0
    #
    SSL3_VERSION: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # TLS 1.1
    #
    TLS1_1_VERSION: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # TLS 1.2
    #
    TLS1_2_VERSION: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # TLS 1.3
    #
    TLS1_3_VERSION: Integer

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.add_certificate(certificate, pkey [, extra_certs]) -> self
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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]?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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]

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # The path to a file containing a PEM-format CA certificate
      #
      def ca_file: () -> String

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # The path to a file containing a PEM-format CA certificate
      #
      def ca_file=: (String ca_file) -> String

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Context certificate
      #
      # The *cert*, *key*, and *extra_chain_cert* attributes are deprecated. It is
      # recommended to use #add_certificate instead.
      #
      def cert: () -> X509::Certificate?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # An OpenSSL::X509::Store used for certificate verification.
      #
      def cert_store: () -> X509::Store?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # An OpenSSL::X509::Store used for certificate verification.
      #
      def cert_store=: (X509::Store store) -> X509::Store

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.ciphers => [[name, version, bits, alg_bits], ...]
      # -->
      # The list of cipher suites configured for this context.
      #
      def ciphers: () -> Array[[ String, String, Integer, Integer ]]

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.ciphers = "cipher1:cipher2:..."
      #   - ctx.ciphers = [name, ...]
      #   - ctx.ciphers = [[name, version, bits, alg_bits], ...]
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # A certificate or Array of certificates that will be sent to the client.
      #
      def client_ca: () -> (Array[X509::Certificate] | X509::Certificate)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # A certificate or Array of certificates that will be sent to the client.
      #
      def client_ca=: (Array[X509::Certificate] | X509::Certificate client_ca) -> void

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.ecdh_curves = curve_list -> curve_list
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.enable_fallback_scsv() => nil
      # -->
      # Activate TLS_FALLBACK_SCSV for this context. See RFC 7507.
      #
      def enable_fallback_scsv: () -> nil

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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]?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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]

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.flush_sessions(time) -> self
      # -->
      # Removes sessions in the internal cache that have expired at *time*.
      #
      def flush_sessions: (Time time) -> self

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
      #   - ctx.max_version = :TLS1_2
      #   - ctx.max_version = nil
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
      #   - ctx.min_version = :TLS1_2
      #   - ctx.min_version = nil
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - options()
      # -->
      # Gets various OpenSSL options.
      #
      def options: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - options=(p1)
      # -->
      # Sets various OpenSSL options.
      #
      def options=: (Integer ssl_options) -> Integer

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.security_level -> Integer
      # -->
      # Returns the security level for the context.
      #
      # See also OpenSSL::SSL::SSLContext#security_level=.
      #
      def security_level: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.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

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # 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)

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.session_add(session) -> true | false
      # -->
      # Adds *session* to the session cache.
      #
      def session_add: (Session) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.session_cache_mode -> Integer
      # -->
      # The current session cache mode.
      #
      def session_cache_mode: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.session_cache_mode=(integer) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.session_cache_size -> Integer
      # -->
      # Returns the current session cache size.  Zero is used to represent an
      # unlimited cache size.
      #
      def session_cache_size: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.session_cache_size=(integer) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.session_cache_stats -> Hash
      # -->
      # 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]

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.session_remove(session) -> true | false
      # -->
      # Removes *session* from the session cache.
      #
      def session_remove: (Session session) -> bool

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - ctx.set_params(params = {}) -> params
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.setup => Qtrue # first time
      #   - ctx.setup => nil # thereafter
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Maximum session lifetime in seconds.
      #
      alias ssl_timeout timeout

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Maximum session lifetime in seconds.
      #
      alias ssl_timeout= timeout=

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - ctx.ssl_version = :TLSv1
      #   - ctx.ssl_version = "SSLv23"
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Maximum session lifetime in seconds.
      #
      def timeout: () -> Integer?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Maximum session lifetime in seconds.
      #
      def timeout=: (Integer) -> Integer

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # 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)

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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)

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Number of CA certificates to walk when verifying a certificate chain.
      #
      def verify_depth: () -> Integer?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Number of CA certificates to walk when verifying a certificate chain.
      #
      def verify_depth=: (Integer) -> Integer

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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?

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - SSLContext.new           -> ctx
      #   - SSLContext.new(:TLSv1)   -> ctx
      #   - SSLContext.new("SSLv23") -> ctx
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ctx.set_minmax_proto_version(min, max) -> nil
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # The list of available SSL/TLS methods. This constant is only provided for
      # backwards compatibility.
      #
      METHODS: Array[Symbol]

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Both client and server sessions are added to the session cache
      #
      SESSION_CACHE_BOTH: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Client sessions are added to the session cache
      #
      SESSION_CACHE_CLIENT: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and
      # SESSION_CACHE_NO_INTERNAL_STORE.
      #
      SESSION_CACHE_NO_INTERNAL: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Never automatically store sessions in the internal store.
      #
      SESSION_CACHE_NO_INTERNAL_STORE: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # No session caching for client or server
      #
      SESSION_CACHE_OFF: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
      # Server sessions are added to the session cache
      #
      SESSION_CACHE_SERVER: Integer
    end

    # <!-- rdoc-file=ext/openssl/ossl_ssl.c -->
    # 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

    # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
    # SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
    #
    class SSLServer
      include OpenSSL::SSL::SocketForwarder

      public

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - accept()
      # -->
      # Works similar to TCPServer#accept.
      #
      def accept: () -> SSLSocket

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - close()
      # -->
      # See IO#close for details.
      #
      def close: () -> nil

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - listen(backlog=Socket::SOMAXCONN)
      # -->
      # See TCPServer#listen for details.
      #
      def listen: (Integer backlog) -> void

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - shutdown(how=Socket::SHUT_RDWR)
      # -->
      # See BasicSocket#shutdown for details.
      #
      def shutdown: (Symbol | String | Integer how) -> void

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # When true then #accept works exactly the same as TCPServer#accept
      #
      def start_immediately: () -> bool

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # When true then #accept works exactly the same as TCPServer#accept
      #
      def start_immediately=: [U] (boolish) -> U

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - to_io()
      # -->
      # Returns the TCPServer passed to the SSLServer when initialized.
      #
      def to_io: () -> (TCPServer | UNIXServer)

      private

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - new(svr, ctx)
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil)
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.accept => self
      # -->
      # Waits for a SSL/TLS client to initiate a handshake.
      #
      def accept: () -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.accept_nonblock([options]) => 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)

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.alpn_protocol => String | nil
      # -->
      # Returns the ALPN protocol string that was finally selected by the server
      # during the handshake.
      #
      def alpn_protocol: () -> String?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.cert => cert or nil
      # -->
      # The X509 certificate for this socket endpoint.
      #
      def cert: () -> X509::Certificate?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.cipher -> nil or [name, version, bits, alg_bits]
      # -->
      # Returns the cipher suite actually used in the current session, or nil if no
      # session has been established.
      #
      def cipher: () -> [ String, String, Integer, Integer ]?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.client_ca => [x509name, ...]
      # -->
      # 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)

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.connect => self
      # -->
      # Initiates an SSL/TLS handshake with a server.
      #
      def connect: () -> self

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.connect_nonblock([options]) => 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)

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # The SSLContext object used in this connection.
      #
      def context: () -> SSLContext

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.finished_message => "finished message"
      # -->
      # Returns the last **Finished** message sent
      #
      def finished_message: () -> String?

      def hostname: () -> String?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.hostname = hostname -> hostname
      # -->
      # Sets the server hostname used for SNI. This needs to be set before
      # SSLSocket#connect.
      #
      def hostname=: (String) -> String

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # The underlying IO object.
      #
      def io: () -> BasicSocket

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.npn_protocol => String | nil
      # -->
      # Returns the protocol string that was finally selected by the client during the
      # handshake.
      #
      def npn_protocol: () -> String?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.peer_cert => cert or nil
      # -->
      # The X509 certificate for this socket's peer.
      #
      def peer_cert: () -> X509::Certificate?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.peer_cert_chain => [cert, ...] or nil
      # -->
      # The X509 certificate chain for this socket's peer.
      #
      def peer_cert_chain: () -> Array[X509::Certificate]?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.peer_finished_message => "peer finished message"
      # -->
      # Returns the last **Finished** message received
      #
      def peer_finished_message: () -> String?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.pending => Integer
      # -->
      # The number of bytes that are immediately available for reading.
      #
      def pending: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - ssl.post_connection_check(hostname) -> true
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - ssl.session -> aSession
      # -->
      # Returns the SSLSession object currently used, or nil if the session is not
      # established.
      #
      def session: () -> Session?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.session = session -> session
      # -->
      # Sets the Session to be used when the connection is established.
      #
      def session=: (Session) -> Session

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.session_reused? -> true | false
      # -->
      # Returns `true` if a reused session was negotiated during the handshake.
      #
      def session_reused?: () -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.ssl_version => String
      # -->
      # Returns a String representing the SSL/TLS version that was negotiated for the
      # connection, for example "TLSv1.2".
      #
      def ssl_version: () -> tls_version

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.state => string
      # -->
      # A description of the current connection state. This is for diagnostic purposes
      # only.
      #
      def state: () -> String

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # Whether to close the underlying socket as well, when the SSL/TLS connection is
      # shut down. This defaults to `false`.
      #
      def sync_close: () -> bool

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - ssl.sysclose => nil
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.sysread(length) => string
      #   - ssl.sysread(length, buffer) => buffer
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.syswrite(string) => Integer
      # -->
      # Writes *string* to the SSL connection.
      #
      def syswrite: (String data) -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.tmp_key => PKey or nil
      # -->
      # Returns the ephemeral key used in case of forward secrecy cipher.
      #
      def tmp_key: () -> PKey::PKey?

      # <!-- rdoc-file=ext/openssl/lib/openssl/ssl.rb -->
      # The underlying IO object.
      #
      alias to_io io

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.verify_result => Integer
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - client_cert_cb()
      # -->
      #
      def client_cert_cb: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - SSLSocket.new(io) => aSSLSocket
      #   - SSLSocket.new(io, ctx) => aSSLSocket
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - session_get_cb()
      # -->
      #
      def session_get_cb: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - session_new_cb()
      # -->
      #
      def session_new_cb: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.stop => nil
      # -->
      # Sends "close notify" to the peer and tries to shut down the SSL connection
      # gracefully.
      #
      def stop: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.sysread_nonblock(length) => string
      #   - ssl.sysread_nonblock(length, buffer) => buffer
      #   - ssl.sysread_nonblock(length[, buffer [, opts]) => buffer
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl.c
      #   - ssl.syswrite_nonblock(string) => Integer
      # -->
      # Writes *string* to the SSL connection in a non-blocking manner.  Raises an
      # SSLError if writing would block.
      #
      def syswrite_nonblock: (*untyped) -> untyped

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - tmp_dh_callback()
      # -->
      #
      def tmp_dh_callback: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - tmp_ecdh_callback()
      # -->
      #
      def tmp_ecdh_callback: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - using_anon_cipher?()
      # -->
      #
      def using_anon_cipher?: () -> untyped
    end

    class Session
      public

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session1 == session2 -> boolean
      # -->
      # Returns `true` if the two Session is the same, `false` if not.
      #
      def ==: (instance other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.id -> String
      # -->
      # Returns the Session ID.
      #
      def id: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.time -> Time
      # -->
      # Returns the time at which the session was established.
      #
      def time: () -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.time = time
      #   - session.time = integer
      # -->
      # Sets start time of the session. Time resolution is in seconds.
      #
      def time=: (Time | Integer start_time) -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.timeout -> Integer
      # -->
      # Returns the timeout value set for the session, in seconds from the established
      # time.
      #
      def timeout: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.timeout = integer
      # -->
      # Sets how long until the session expires in seconds.
      #
      def timeout=: (Integer timeout) -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.to_der -> String
      # -->
      # Returns an ASN1 encoded String that contains the Session object.
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.to_pem -> String
      # -->
      # Returns a PEM encoded String that contains the Session object.
      #
      def to_pem: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - session.to_text -> String
      # -->
      # Shows everything in the Session object. This is for diagnostic purposes.
      #
      def to_text: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - Session.new(ssl_socket) -> Session
      #   - Session.new(string) -> Session
      # -->
      # Creates a new Session object from an instance of SSLSocket or DER/PEM encoded
      # String.
      #
      def initialize: (SSLSocket | String sock_or_str) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_ssl_session.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void

      class SessionError < OpenSSL::OpenSSLError
      end
    end

    module SocketForwarder
      public

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - addr()
      # -->
      #
      def addr: () -> Addrinfo?

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - closed?()
      # -->
      #
      def closed?: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - do_not_reverse_lookup=(flag)
      # -->
      #
      def do_not_reverse_lookup=: (boolish flag) -> boolish

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - fcntl(*args)
      # -->
      #
      def fcntl: (*untyped args) -> untyped

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - fileno()
      # -->
      # The file descriptor for the socket.
      #
      def fileno: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - getsockopt(level, optname)
      # -->
      #
      def getsockopt: (Symbol | Integer level, Symbol | Integer optname) -> (Integer | boolish | String)

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - peeraddr()
      # -->
      #
      def peeraddr: () -> untyped

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/ssl.rb
      #   - setsockopt(level, optname, optval)
      # -->
      #
      def setsockopt: (untyped level, untyped optname, untyped optval) -> untyped
    end
  end

  # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
  # 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
    # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
    # 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]

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - factory.create_timestamp(key, certificate, request) -> Response
      # -->
      # 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

    # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.algorithm    -> string
      # -->
      # Returns the 'short name' of the object identifier that represents the
      # algorithm that was used to create the message imprint digest.
      #
      def algorithm: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.algorithm = "string"    -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.cert_requested = boolean -> true or false
      # -->
      # Specify whether the response shall contain the timestamp authority's
      # certificate or not. The default value is `true`.
      #
      def cert_requested=: [U] (boolish) -> U

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.cert_requested?  -> true or false
      # -->
      # Indicates whether the response shall contain the timestamp authority's
      # certificate or not.
      #
      def cert_requested?: () -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.message_imprint    -> string or nil
      # -->
      # Returns the message imprint (digest) of the data to be timestamped.
      #
      def message_imprint: () -> String?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.message_imprint = "string"    -> string
      # -->
      # Set the message imprint digest.
      #
      def message_imprint=: (String) -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.nonce    -> BN or nil
      # -->
      # Returns the nonce (number used once) that the server shall include in its
      # response.
      #
      def nonce: () -> BN?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.nonce = number    -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.policy_id    -> string or nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.policy_id = "string"   -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.to_der    -> DER-encoded string
      # -->
      # DER-encodes this Request.
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.version -> Integer
      # -->
      # Returns the version of this request. `1` is the default value.
      #
      def version: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - request.version = number    -> Integer
      # -->
      # Sets the version number for this Request. This should be `1` for compliant
      # servers.
      #
      def version=: (Integer) -> Integer

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - OpenSSL::Timestamp::Request.new(file)    -> request
      #   - OpenSSL::Timestamp::Request.new(string)  -> request
      #   - OpenSSL::Timestamp::Request.new          -> empty request
      # -->
      # 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

    # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.failure_info -> nil or symbol
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.status -> BN (never nil)
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.status_text -> Array of strings or nil
      # -->
      # In cases of failure this field may contain an array of strings further
      # describing the origin of the failure.
      #
      def status_text: () -> Array[String]?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.to_der -> string
      # -->
      # Returns the Response in DER-encoded form.
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.token -> nil or OpenSSL::PKCS7
      # -->
      # If a timestamp token is present, this returns it in the form of a
      # OpenSSL::PKCS7.
      #
      def token: () -> PKCS7?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.token_info -> nil or OpenSSL::Timestamp::TokenInfo
      # -->
      # Get the response's token info if present.
      #
      def token_info: () -> TokenInfo?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.tsa_certificate -> OpenSSL::X509::Certificate or nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - response.verify(Request, root_store) -> Response
      #   - response.verify(Request, root_store, [intermediate_cert]) -> Response
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - OpenSSL::Timestamp::Response.new(file)    -> response
      #   - OpenSSL::Timestamp::Response.new(string)  -> response
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
      # Indicates a successful response. Equal to `0`.
      #
      GRANTED: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
      # Indicates a successful response that probably contains modifications from the
      # initial request. Equal to `1`.
      #
      GRANTED_WITH_MODS: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
      # Indicates a failure. No timestamp token was created. Equal to `2`.
      #
      REJECTION: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
      # Indicates a failure. No timestamp token was created. A certificate has been
      # revoked. Equal to `5`.
      #
      REVOCATION_NOTIFICATION: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
      # Indicates a failure. No timestamp token was created. Revocation of a
      # certificate is imminent. Equal to `4`.
      #
      REVOCATION_WARNING: Integer

      # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
      # Indicates a failure. No timestamp token was created. Equal to `3`.
      #
      WAITING: Integer
    end

    # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
    # Generic exception class of the Timestamp module.
    #
    class TimestampError < OpenSSL::OpenSSLError
    end

    # <!-- rdoc-file=ext/openssl/ossl_ts.c -->
    # Immutable and read-only representation of a timestamp token info from a
    # Response.
    #
    class TokenInfo
      public

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.algorithm -> string or nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.gen_time -> Time
      # -->
      # Returns time when this timestamp token was created. If status is GRANTED or
      # GRANTED_WITH_MODS, this is never `nil`.
      #
      def gen_time: () -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.msg_imprint -> string.
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.nonce -> BN or nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.ordering -> true, falses or nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.policy_id -> string or nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.serial_number -> BN or nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.to_der -> string
      # -->
      # Returns the TokenInfo in DER-encoded form.
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - token_info.version -> Integer or nil
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_ts.c
      #   - OpenSSL::Timestamp::TokenInfo.new(file)    -> token-info
      #   - OpenSSL::Timestamp::TokenInfo.new(string)  -> token-info
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - ==(other)
      # -->
      #
      def ==: (instance other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509attr.c
      #   - attr.oid => string
      # -->
      #
      def oid: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509attr.c
      #   - attr.oid = string => string
      # -->
      #
      def oid=: (String) -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509attr.c
      #   - attr.to_der => string
      # -->
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509attr.c
      #   - attr.value => asn1
      # -->
      #
      def value: () -> ASN1::Set

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509attr.c
      #   - attr.value = asn1 => asn1
      # -->
      #
      def value=: (ASN1::ASN1Data) -> ASN1::Set

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509attr.c
      #   - Attribute.new(oid [, value]) => attr
      # -->
      #
      def initialize: (String der) -> void
                    | (String oid, ASN1::ASN1Data value) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509attr.c
      #   - initialize_copy(p1)
      # -->
      #
      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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - ==(other)
      # -->
      #
      def ==: (instance other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - add_extension(p1)
      # -->
      #
      def add_extension: (Extension ext) -> Extension

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - add_revoked(p1)
      # -->
      #
      def add_revoked: (Revoked revoked) -> Revoked

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - extensions()
      # -->
      # Gets X509v3 extensions as array of X509Ext objects
      #
      def extensions: () -> Array[Extension]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - extensions=(p1)
      # -->
      # Sets X509_EXTENSIONs
      #
      def extensions=: (Array[Extension] extensions) -> Array[Extension]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - issuer()
      # -->
      #
      def issuer: () -> X509::Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - issuer=(p1)
      # -->
      #
      def issuer=: (X509::Name issuer) -> X509::Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - last_update()
      # -->
      #
      def last_update: () -> Time?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - last_update=(p1)
      # -->
      #
      def last_update=: (Time last_update) -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - next_update()
      # -->
      #
      def next_update: () -> Time?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - next_update=(p1)
      # -->
      #
      def next_update=: (Time next_update) -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - revoked()
      # -->
      #
      def revoked: () -> Array[Revoked]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - revoked=(p1)
      # -->
      #
      def revoked=: (Array[Revoked]) -> Array[Revoked]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - sign(p1, p2)
      # -->
      #
      def sign: (PKey::PKey key, Digest digest) -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - signature_algorithm()
      # -->
      #
      def signature_algorithm: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - to_der()
      # -->
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - to_pem()
      # -->
      #
      def to_pem: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - to_s()
      # -->
      #
      alias to_s to_pem

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - to_text()
      # -->
      #
      def to_text: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - verify(p1)
      # -->
      #
      def verify: (PKey::PKey key) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - version()
      # -->
      #
      def version: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - version=(p1)
      # -->
      #
      def version=: (Integer) -> Integer

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - new(p1 = v1)
      # -->
      #
      def initialize: (?String der) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509crl.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    class CRLError < OpenSSL::OpenSSLError
    end

    # <!-- rdoc-file=ext/openssl/ossl_x509cert.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert1 == cert2 -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.add_extension(extension) => extension
      # -->
      #
      def add_extension: (Extension ext) -> Extension

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.check_private_key(key) -> true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.extensions => [extension...]
      # -->
      #
      def extensions: () -> Array[Extension]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.extensions = [ext...] => [ext...]
      # -->
      #
      def extensions=: (Array[Extension]) -> Array[Extension]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - inspect()
      # -->
      #
      def inspect: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.issuer => name
      # -->
      #
      def issuer: () -> Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.issuer = name => name
      # -->
      #
      def issuer=: (Name) -> Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.not_after => time
      # -->
      #
      def not_after: () -> Time?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.not_after = time => time
      # -->
      #
      def not_after=: (Time) -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.not_before => time
      # -->
      #
      def not_before: () -> Time?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.not_before = time => time
      # -->
      #
      def not_before=: (Time) -> Time

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - pretty_print(q)
      # -->
      #
      def pretty_print: (untyped q) -> untyped

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.public_key => key
      # -->
      #
      def public_key: () -> PKey::PKey

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.public_key = key
      # -->
      #
      def public_key=: (PKey::PKey pkey) -> PKey::PKey

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.serial => integer
      # -->
      #
      def serial: () -> BN

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.serial = integer => integer
      # -->
      #
      def serial=: (bn serial) -> bn

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.sign(key, digest) => self
      # -->
      #
      def sign: (PKey::PKey key, String digest) -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.signature_algorithm => string
      # -->
      #
      def signature_algorithm: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.subject => name
      # -->
      #
      def subject: () -> Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.subject = name => name
      # -->
      #
      def subject=: (Name) -> Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.to_der => string
      # -->
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.to_pem => string
      # -->
      #
      def to_pem: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - to_s()
      # -->
      #
      alias to_s to_pem

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.to_text => string
      # -->
      #
      def to_text: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.verify(key) => true | false
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.version => integer
      # -->
      #
      def version: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - cert.version = integer => integer
      # -->
      #
      def version=: (Integer) -> Integer

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - Certificate.new => cert
      #   - Certificate.new(string) => cert
      # -->
      #
      def initialize: (?String pem) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509cert.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    class CertificateError < OpenSSL::OpenSSLError
    end

    class Extension
      include OpenSSL::Marshal

      extend OpenSSL::Marshal::ClassMethods

      public

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - ==(other)
      # -->
      #
      def ==: (instance other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - critical=(p1)
      # -->
      #
      def critical=: [U] (boolish) -> U

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - critical?()
      # -->
      #
      def critical?: () -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - oid()
      # -->
      #
      def oid: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - oid=(p1)
      # -->
      #
      def oid=: (String oid) -> String

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - to_a()
      # -->
      #
      def to_a: () -> [ String, String, bool ]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - to_der()
      # -->
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - to_h()
      # -->
      #
      def to_h: () -> Hash[String, untyped]

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - to_s()
      # -->
      #
      def to_s: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - value()
      # -->
      #
      def value: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - value=(p1)
      # -->
      #
      def value=: (String | ASN1::_ToDer data) -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - value_der()
      # -->
      #
      def value_der: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - OpenSSL::X509::Extension.new(der)
      #   - OpenSSL::X509::Extension.new(oid, value)
      #   - OpenSSL::X509::Extension.new(oid, value, critical)
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void

      module AuthorityInfoAccess
        include OpenSSL::X509::Extension::Helpers

        public

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - ca_issuer_uris()
        # -->
        # 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]?

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - ocsp_uris()
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - parse_aia_asn1()
        # -->
        #
        def parse_aia_asn1: () -> untyped
      end

      module AuthorityKeyIdentifier
        include OpenSSL::X509::Extension::Helpers

        public

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - authority_key_identifier()
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - crl_uris()
        # -->
        # 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

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - find_extension(oid)
        # -->
        #
        def find_extension: (String oid) -> Extension?
      end

      module SubjectKeyIdentifier
        include OpenSSL::X509::Extension::Helpers

        public

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - subject_key_identifier()
        # -->
        # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - ef.create_ext(ln_or_sn, "value", critical = false) -> X509::Extension
      #   - ef.create_ext(ln_or_sn, "critical,value")          -> X509::Extension
      # -->
      # Creates a new X509::Extension with passed values. See also x509v3_config(5).
      #
      def create_ext: (String oid, String value, ?boolish critical) -> Extension

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - create_ext_from_array(ary)
      # -->
      #
      def create_ext_from_array: ([ String, String ] | [ String, String, boolish ] ary) -> Extension

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - create_ext_from_hash(hash)
      # -->
      #
      def create_ext_from_hash: (Hash[String, String | boolish] hash) -> Extension

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - create_ext_from_string(str)
      # -->
      #
      def create_ext_from_string: (String str) -> Extension

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - create_extension(*arg)
      # -->
      #
      def create_extension: (String oid, String value, ?boolish critical) -> Extension

      def crl: () -> CRL?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - crl=(p1)
      # -->
      #
      def crl=: (CRL crl) -> CRL

      def issuer_certificate: () -> Certificate?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - issuer_certificate=(p1)
      # -->
      #
      def issuer_certificate=: (Certificate cert) -> Certificate

      def subject_certificate: () -> Certificate?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - subject_certificate=(p1)
      # -->
      #
      def subject_certificate=: (Certificate cert) -> Certificate

      def subject_request: () -> Request?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - subject_request=(p1)
      # -->
      #
      def subject_request=: (Request request) -> Request

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509ext.c
      #   - new(p1 = v1, p2 = v2, p3 = v3, p4 = v4)
      # -->
      #
      def initialize: (?Certificate? issuer_cert, ?Certificate? subject_cert, ?Request? request, ?CRL? crl) -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - parse(str, template=OBJECT_TYPE_TEMPLATE)
      # -->
      #
      alias self.parse self.parse_openssl

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.add_entry(oid, value [, type], loc: -1, set: 0) => self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.cmp(other) -> -1 | 0 | 1 | nil
      #   - name <=> other  -> -1 | 0 | 1 | nil
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.eql?(other) -> true | false
      # -->
      # Returns true if *name* and *other* refer to the same hash key.
      #
      def eql?: (instance other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.hash => integer
      # -->
      # The hash value returned is suitable for use as a certificate's filename in a
      # CA path.
      #
      def hash: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.hash_old => integer
      # -->
      # Returns an MD5 based hash used in OpenSSL 0.9.X.
      #
      def hash_old: () -> Integer

      def inspect: () -> String

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - pretty_print(q)
      # -->
      #
      def pretty_print: (untyped q) -> untyped

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.to_a => [[name, data, type], ...]
      # -->
      # Returns an Array representation of the distinguished name suitable for passing
      # to ::new
      #
      def to_a: () -> Array[[ String, String, Integer ]]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.to_der => string
      # -->
      # Converts the name to DER encoding
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.to_s         -> string
      #   - name.to_s(format) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - name.to_utf8 -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - X509::Name.new                               => name
      #   - X509::Name.new(der)                          => name
      #   - X509::Name.new(distinguished_name)           => name
      #   - X509::Name.new(distinguished_name, template) => name
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509name.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void

      # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
      # A flag for #to_s.
      #
      # Breaks the name returned into multiple lines if longer than 80 characters.
      #
      COMPAT: Integer

      # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
      # The default object type for name entries.
      #
      DEFAULT_OBJECT_TYPE: Integer

      # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
      # A flag for #to_s.
      #
      # Returns a multiline format.
      #
      MULTILINE: Integer

      # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
      # The default object type template for name entries.
      #
      OBJECT_TYPE_TEMPLATE: template

      # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
      # A flag for #to_s.
      #
      # Returns a more readable format than RFC2253.
      #
      ONELINE: Integer

      # <!-- rdoc-file=ext/openssl/ossl_x509name.c -->
      # 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

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - expand_hexstring(str)
        # -->
        #
        def expand_hexstring: (untyped str) -> untyped

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - expand_pair(str)
        # -->
        #
        def expand_pair: (untyped str) -> untyped

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - expand_value(str1, str2, str3)
        # -->
        #
        def expand_value: (untyped str1, untyped str2, untyped str3) -> untyped

        # <!--
        #   rdoc-file=ext/openssl/lib/openssl/x509.rb
        #   - scan(dn)
        # -->
        #
        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

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - ==(other)
      # -->
      #
      def ==: (untyped other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - add_attribute(p1)
      # -->
      #
      def add_attribute: (Attribute attribute) -> Attribute

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - attributes()
      # -->
      #
      def attributes: () -> Array[Attribute]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - attributes=(p1)
      # -->
      #
      def attributes=: (Array[Attribute] attributes) -> Array[Attribute]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - public_key()
      # -->
      #
      def public_key: () -> PKey::PKey

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - public_key=(p1)
      # -->
      #
      def public_key=: (PKey::PKey public_key) -> PKey::PKey

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - sign(p1, p2)
      # -->
      #
      def sign: (PKey::PKey key, Digest | String digest) -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - signature_algorithm()
      # -->
      #
      def signature_algorithm: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - subject()
      # -->
      #
      def subject: () -> Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - subject=(p1)
      # -->
      #
      def subject=: (Name subject) -> Name

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - to_der()
      # -->
      #
      def to_der: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - to_pem()
      # -->
      #
      def to_pem: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - to_s()
      # -->
      #
      alias to_s to_pem

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - to_text()
      # -->
      #
      def to_text: () -> String

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - verify(p1)
      # -->
      # Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
      #
      def verify: (PKey::PKey key) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - version()
      # -->
      #
      def version: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - version=(p1)
      # -->
      #
      def version=: (Integer version) -> Integer

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - new(p1 = v1)
      # -->
      #
      def initialize: (?String der) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509req.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    class RequestError < OpenSSL::OpenSSLError
    end

    class Revoked
      public

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - ==(other)
      # -->
      #
      def ==: (untyped other) -> bool

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - add_extension(p1)
      # -->
      #
      def add_extension: (Extension ext) -> Extension

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - extensions()
      # -->
      # Gets X509v3 extensions as array of X509Ext objects
      #
      def extensions: () -> Array[Extension]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - extensions=(p1)
      # -->
      # Sets X509_EXTENSIONs
      #
      def extensions=: (Array[Extension] extensions) -> Array[Extension]

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - serial()
      # -->
      #
      def serial: () -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - serial=(p1)
      # -->
      #
      def serial=: (Integer integer) -> Integer

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - time()
      # -->
      #
      def time: () -> Time?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - time=(p1)
      # -->
      #
      def time=: (Time time) -> Time

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - to_der()
      # -->
      #
      def to_der: () -> String

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - new(*args)
      # -->
      #
      def initialize: (*untyped) -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509revoked.c
      #   - initialize_copy(p1)
      # -->
      #
      def initialize_copy: (instance) -> void
    end

    class RevokedError < OpenSSL::OpenSSLError
    end

    # <!-- rdoc-file=ext/openssl/ossl_x509store.c -->
    # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.add_cert(cert) -> self
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.add_crl(crl) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.add_file(file) -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.add_path(path) -> 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

      # <!-- rdoc-file=ext/openssl/ossl_x509store.c -->
      # The certificate chain constructed by the last call of #verify.
      #
      # See also StoreContext#chain.
      #
      def chain: () -> Array[Certificate]?

      # <!-- rdoc-file=ext/openssl/ossl_x509store.c -->
      # The error code set by the last call of #verify.
      #
      # See also StoreContext#error.
      #
      def error: () -> Integer?

      # <!-- rdoc-file=ext/openssl/ossl_x509store.c -->
      # The description for the error code set by the last call of #verify.
      #
      # See also StoreContext#error_string.
      #
      def error_string: () -> String?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.flags = flags
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.purpose = purpose
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.set_default_paths
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.time = time
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.trust = trust
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - store.verify(cert, chain = nil) -> true | false
      # -->
      # 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

      # <!-- rdoc-file=ext/openssl/ossl_x509store.c -->
      # 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)

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - verify_callback=(p1)
      # -->
      # General callback for OpenSSL verify
      #
      def verify_callback=: [U] (^(bool preverify_ok, StoreContext store_ctx) -> boolish) -> U

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - X509::Store.new => store
      # -->
      # Creates a new X509::Store.
      #
      def initialize: () -> void
    end

    # <!-- rdoc-file=ext/openssl/ossl_x509store.c -->
    # A StoreContext is used while validating a single certificate and holds the
    # status involved.
    #
    class StoreContext
      public

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.chain -> nil | Array of X509::Certificate
      # -->
      # Returns the verified chain.
      #
      # See also the man page X509_STORE_CTX_set0_verified_chain(3).
      #
      def chain: () -> Array[Certificate]?

      # <!--
      #   rdoc-file=ext/openssl/lib/openssl/x509.rb
      #   - cleanup()
      # -->
      #
      def cleanup: () -> void

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.current_cert -> X509::Certificate
      # -->
      # Returns the certificate which caused the error.
      #
      # See also the man page X509_STORE_CTX_get_current_cert(3).
      #
      def current_cert: () -> Certificate

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.current_crl -> X509::CRL
      # -->
      # Returns the CRL which caused the error.
      #
      # See also the man page X509_STORE_CTX_get_current_crl(3).
      #
      def current_crl: () -> CRL

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.error -> Integer
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.error = error_code
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.error_depth -> 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.error_string -> String
      # -->
      # 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?

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.flags = flags
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.purpose = purpose
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.time = time
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.trust = trust
      # -->
      # 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

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - stctx.verify -> true | false
      # -->
      # Performs the certificate verification using the parameters set to *stctx*.
      #
      # See also the man page X509_verify_cert(3).
      #
      def verify: () -> bool

      private

      # <!--
      #   rdoc-file=ext/openssl/ossl_x509store.c
      #   - StoreContext.new(store, cert = nil, untrusted = nil)
      # -->
      # 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
