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_ext/bio.cropenssl_ext/pkey.cr
openssl_ext/rsa.cr