1. Basic Web SSL Server
1.1. Generate a self signed certificate - without a Certificat Authority (CA)
https://www.akadia.com/services/ssh_test_certificate.html * Step 1: Generate a Private Key
$ openssl genrsa -des3 -out server.key 1024
-
Step 2: Generate a CSR
$ openssl req -new -key server.key -out server.csr
-
Step 3: Remove Passphrase from Key
$ cp server.key server.key.org
$ openssl rsa -in server.key.org -out server.key
-
Step 4: Generating a Self-Signed Certificate (without a CA)
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
1.2. Generate a self signed certificate - as your own Certificate Authority (CA)
This allows you to import the CA into your OS and simplifies the permissions.
TODO: Figure out how to import into a web-client without importing into the OS.
-
https://deliciousbrains.com/ssl-certificate-authority-for-local-https-development/
-
https://www.makethenmakeinstall.com/2014/05/ssl-client-authentication-step-by-step/
-
https://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl
-
Step 1 - create ca key and authority cert
openssl req -x509 -newkey rsa:4096 -keyout ca_auth.key -out ca_auth.pem -days 365 -subj '/CN=localhost'
-
step 2 - import the CA_auth into your OS (as described in the various articles)
ca_auth.pem
-
step 3 - create a self-signed server cert - start with a server key
openssl genrsa -out server.key 4096
-
step 4 - *make the certificate reqest 'csr' using the server key
openssl req -new -key server.key -out server_req.csr -subj '/CN=localhost'
-
Step 5 - generate the self-signed certificate based on the request & the CA
openssl x509 -req -in server_req.csr -CA ca_auth.pem -CAkey ca_auth.key -CAcreateserial -out server.crt -days 365 -sha256
1.3. Write the SSL Server Code
Helpful Docs:
# A very basic HTTPS server
require "openssl"
require "http/server"
server = HTTP::Server.new do |context|
# get incoming request
path = context.request.path
# log request to stdout - for fun
puts "HTTP request for path: #{path}"
# build / send response
context.response.content_type = "text/plain"
context.response.print "Hello world, got #{path}!"
end
# configure the ssl service
tls_config = OpenSSL::SSL::Context::Server.new
tls_config.private_key = "./server.key"
tls_config.certificate_chain = "./server.crt"
# 'bind' the ssl server to the web server
server.bind_tls "localhost", 8443, tls_config
puts "Listening on http://127.0.0.1:8443"
server.listen
Run with
$ crystal code/crystal/src/web_server/web_ssl.cr
Now open your browser to (dismiss all the warnings about the self-signed cert) * https://localhost:8443 * https://localhost:8443/bill
1.4. Use the Custom TLS Web Client
require "openssl"
require "http/client"
tls_client = OpenSSL::SSL::Context::Client.new
tls_client.verify_mode = OpenSSL::SSL::VerifyMode::NONE
web_client = HTTP::Client.new(host: "localhost", port: 8443, tls: tls_client)
response = web_client.get "/"
puts response.status_code
response.body.each_line{ |line| puts line }
response = web_client.get "/bill"
puts response.status_code
response.body.lines.each { |line| puts line }
Run with (after starting the ssl_server)
$ crystal code/crystal/src/web_server/web_ssl_client.cr