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 eitherOpenSSL orLibreSSL.

WARNING This module should not be used without 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 digest withOpenSSL::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 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 byopening an issue.

Usage Example

Server side

AnSSL server is created with aTCPServer and aSSL::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

AnSSL client is created with 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 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