Generating TLS certs for testing is difficult. Most guides have incomprehensible commands that require security knowledge to operate.
Cloudflare open-sourced their well-trusted Golang TLS library,
cloudflare/cfssl
. It has sane defaults and is constantly updated with best practices.
We've compiled it to
WebAssembly
to generate certs in your browser.
Here are some examples of doing mTLS in various languages.
Ruby
Go
Python
Javascript
require 'openssl'
require 'webrick'
require 'webrick/https'
cert = OpenSSL::X509::Certificate.new File.read './server.pem'
pkey = OpenSSL::PKey::EC.new File.read './server-key.pem'
server = WEBrick::HTTPServer.new(:Port => 443,
:SSLEnable => true,
:SSLCertificate => cert,
:SSLPrivateKey => pkey,
:SSLCACertificateFile => './ca.pem')
server.mount_proc '/' do |req, res|
res.body = 'Hi!'
end
server.start
package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"net/http"
)
func main() {
caCert, err := ioutil.ReadFile("./ca.pem")
if err != nil {
log.Fatalf("reading ca cert: %s", err)
}
certPool := x509.NewCertPool()
certPool.AppendCertsFromPEM(caCert)
conf := &tls.Config{
ClientCAs: certPool,
}
conf.BuildNameToCertificate()
httpServer := &http.Server{
Addr: ":443",
TLSConfig: conf,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}),
}
err = httpServer.ListenAndServeTLS("./server.pem", "./server-key.pem")
if err != nil {
log.Fatalf("listen and serving: %s", err)
}
}
import ssl
from flask import Flask
app = Flask(__name__)
port = 443
@app.route('/')
def index():
return 'Hi!'
ctx = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
ctx.load_verify_locations(cafile='./ca.pem')
ctx.load_cert_chain(
certfile='./server.pem',
keyfile='./server-key.pem',
)
ctx.verify_mode = ssl.CERT_REQUIRED
app.run(debug=True, ssl_context=ctx, host="0.0.0.0", port=port)
const fs = require('fs');
const https = require('https');
const port = 443;
const server = https.createServer(
{
cert: fs.readFileSync('./server.pem'),
key: fs.readFileSync('./server-key.pem'),
ca: fs.readFileSync('./ca.pem'),
},
(req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hi!\n');
}
);
server.listen(port);
require 'faraday'
require 'openssl'
cert = OpenSSL::X509::Certificate.new File.read './client.pem'
pkey = OpenSSL::PKey::EC.new File.read './client-key.pem'
connection = Faraday::Connection.new 'https://server/', :ssl => {
:client_cert => cert,
:client_key => pkey,
:ca_file => './ca.pem'
}
resp = connection.get '/'
if resp.status != 200
exit 1
end
exit 0
package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"net/http"
)
func main() {
cert, err := tls.LoadX509KeyPair("./client.pem", "./client-key.pem")
if err != nil {
log.Fatalf("loading key pair: %s", err)
}
caCert, err := ioutil.ReadFile("./ca.pem")
if err != nil {
log.Fatalf("reading ca cert: %s", err)
}
certPool := x509.NewCertPool()
certPool.AppendCertsFromPEM(caCert)
conf := &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: certPool,
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: conf,
},
}
resp, err := client.Get("https://server/")
if err != nil {
log.Fatalf("sending request: %s", err)
}
if resp.StatusCode != http.StatusOK {
log.Fatalf("expected status %d but got %d", http.StatusOK, resp.StatusCode)
}
}
import requests
resp = requests.get(
'https://server/',
cert=('./client.pem', './client-key.pem'),
verify='./ca.pem',
)
if resp.status_code != 200:
print('expected status_code 200 but got {}'.format(resp.status_code))
exit(1)
const fs = require('fs');
const https = require('https');
https.get(
{
hostname: 'server',
port: 443,
path: '/',
method: 'GET',
cert: fs.readFileSync('./client.pem'),
key: fs.readFileSync('./client-key.pem'),
ca: fs.readFileSync('./ca.pem')
},
res => {
if (res.statusCode != 200) {
console.error(`expected status 200 but found ${res.statusCode}`);
return process.exit(1);
}
}
).on('error', error => {
console.error(error);
process.exit(1);
});
Want to add something? Find a bug? This project is open-source, please send PRs to github.com/jchorl/tlscerts. Feel free to also get in touch at [email protected].