# module OpenSSL

##
Overview

The OpenSSL module allows for access to Secure Sockets Layer (SSL) and Transport Layer Security (TLS) encryption, as well as classes for encrypting data, decrypting data, and computing hashes. It uses the SSL library provided by the operating system, which may be either OpenSSL or LibreSSL.

WARNING This module should not be used without first reading the Security considerations.

To create secure sockets, use either `OpenSSL::SSL::Socket::Client` for client applications, or `OpenSSL::SSL::Socket::Server` for servers. These classes use a default context, but you can provide your own by supplying an `OpenSSL::SSL::Context`. For more control, consider subclassing `OpenSSL::SSL::Socket`.

Hashing algorithms are provided by classes such as `Digest::SHA256` and `Digest::MD5`. If you need a different option, you can initialize one using the name of the digest with `OpenSSL::Digest`. A Hash-based Message Authentication Code (HMAC) can be computed using `HMAC` and specifying a digest `Algorithm`.

The `OpenSSL::Cipher` class can be used for encrypting and decrypting data.

NOTE To use `OpenSSL`, you must explicitly import it using the `require "openssl"` statement.

##
Security Considerations

Crystal aims to provide reasonable configuration defaults in accordance with Mozilla's recommendations. However, these defaults may not be suitable for your application. It is recommended that you refer to the Open Worldwide Application Security Project (OWASP) cheat sheet on implementing transport layer protection to ensure the appropriate configuration for your use.

If you come across any shortcomings or spots for improvement in Crystal's configuration options, please don't hesitate to let us know by opening an issue.

##
Usage Example

###
Server side

An `SSL` server is created with a `TCPServer` and a `SSL::Context`. You can then use the SSL server like an ordinary TCP server.

NOTE For the below example to work, a certificate and private key should be attained.

    require "openssl"
    require "socket"

    PORT = ENV["PORT"] ||= "5555"

    # Bind new TCPServer to PORT
    socket = TCPServer.new(PORT.to_i)

    context = OpenSSL::SSL::Context::Server.new
    context.private_key = "/path/to/private.key"
    context.certificate_chain = "/path/to/public.cert"

    puts "Server is up. Listening on port #{PORT}."

    socket.accept do |client|
      puts "Got client"

      bytes = Bytes.new(20)

      OpenSSL::SSL::Socket::Server.open(client, context) do |ssl_socket|
        ssl_socket.read(bytes)
      end

      puts "Client said: #{String.new(bytes)}"
    end

    socket.close
    puts "Server has stopped."

###
Client side

An `SSL` client is created with a `TCPSocket` and a `SSL::Context`. Unlike a SSL server, a client does not require a certificate or private key.

NOTE By default, closing an `SSL::Socket` does not close the underlying socket. You need to set `SSL::Socket#sync_close=` to true if you want this behaviour.

    require "openssl"
    require "socket"

    PORT = ENV["PORT"] ||= "5555"

    # Bind TCPSocket to PORT and open a connection
    TCPSocket.open("127.0.0.1", PORT) do |socket|
      context = OpenSSL::SSL::Context::Client.new

      OpenSSL::SSL::Socket::Client.open(socket, context) do |ssl_socket|
        ssl_socket << "Hello from client!"
      end
    end

##
Defined in:

openssl.cr
openssl/algorithm.cr
openssl/digest.cr
openssl/error.cr