module OpenSSL

Overview

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

WARNING This module should not be usedwithout first reading theSecurity considerations.

To create secure sockets, use eitherOpenSSL::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 anOpenSSL::SSL::Context. For more control, consider subclassingOpenSSL::SSL::Socket.

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

TheOpenSSL::Cipher class can be used for encrypting and decrypting data.

NOTE To useOpenSSL, you must explicitly import it using therequire "openssl" statement.

Security Considerations

Crystal aims to provide reasonable configuration defaults in accordancewith 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 byopening an issue.

Usage Example

Server side

AnSSL server is createdwith aTCPServer and aSSL::Context. You can then use the SSL server like an ordinary TCP server.

NOTE For the below example towork, 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

AnSSL client is createdwith aTCPSocket and aSSL::Context. Unlike a SSL server, a client does not require a certificate or private key.

NOTE By default, closing anSSL::Socket does not close the underlying socket. You need to setSSL::Socket#sync_close= to true if youwant 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
openssl/ktls.cr