Skip to content

Instantly share code, notes, and snippets.

@mmalone
Created February 12, 2019 22:14
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmalone/a24921292392bd5fbe5531e9aec76c40 to your computer and use it in GitHub Desktop.
Save mmalone/a24921292392bd5fbe5531e9aec76c40 to your computer and use it in GitHub Desktop.
Using `step certificate` without the online step CA
# Create a root certificate and signing key.
$ step certificate create "Root CA" root.crt root.key --profile root-ca
Please enter the password to encrypt the private key:
Your certificate has been saved in root.crt.
Your private key has been saved in root.key.
# Create an intermediate certificate & signing key. This isn't
# required; we could use the root to sign directly which is
# probably fine for local dev and removes the need to bundle later.
$ step certificate create "Intermediate CA" int.crt int.key --profile intermediate-ca --ca root.crt --ca-key root.key
Please enter the password to decrypt root.key:
Please enter the password to encrypt the private key:
Your certificate has been saved in int.crt.
Your private key has been saved in int.key.
# Create a leaf certificate for our server.
#
# Need --insecure here because we want to encrypt your key with a password,
# but doing so will make it hard to use programatically. So we'll ask for
# no password, but `step` wants the user to acknowledge the risks.
$ step certificate create foo.local foo.crt foo.key --ca int.crt --ca-key int.key --no-password --insecure
Please enter the password to decrypt int.key:
Your certificate has been saved in foo.crt.
Your private key has been saved in foo.key.
# Bundle our leaf and intermediate cert for use by the server. This isn't
# necessary if you don't have an intermediate (you use the root to sign
# directly).
$ step certificate bundle foo.crt int.crt foo-bundle.pem
Your certificate has been saved in foo-bundle.pem.
# Start our server
$ node server.js &
# Create a leaf certificate for our client. Curl will actually
# prompt for a password so we'll keep our key encrypted this time.
$ step certificate create mike mike.crt mike.key --ca int.crt --ca-key int.key
Please enter the password to decrypt int.key:
Please enter the password to encrypt the private key:
Your certificate has been saved in mike.crt.
Your private key has been saved in mike.key.
# Bundle the client cert (again, not necessary of you use the root directly):
$ step certificate bundle mike.crt int.crt mike-bundle.pem
Your certificate has been saved in mike-bundle.pem.
# 💥DO IT!
$ curl --resolve foo.local:8443:127.0.0.1 --cacert root.crt --cert mike-bundle.pem --key mike.key https://foo.local:8443/
Enter PEM pass phrase:
Hello mike, your certificate was issued by Intermediate CA!
const https = require('https');
const tls = require('tls');
const fs = require('fs');
var config = {
ca: './root.crt',
key: './foo.key',
cert: './foo-bundle.pem',
ciphers: 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256',
minVersion: 'TLSv1.2',
maxVersion: 'TLSv1.2'
};
function createSecureContext() {
return tls.createSecureContext({
ca: fs.readFileSync(config.ca),
key: fs.readFileSync(config.key),
cert: fs.readFileSync(config.cert),
ciphers: config.ciphers,
});
}
var ctx = createSecureContext()
fs.watch(config.cert, (event, filename) => {
if (event == 'change') {
ctx = createSecureContext();
}
});
https.createServer({
requestCert: true,
rejectUnauthorized: true,
SNICallback: (servername, cb) => {
cb(null, ctx);
}
}, (req, res) => {
const cert = req.connection.getPeerCertificate()
if (req.client.authorized) {
res.writeHead(200);
res.end(`Hello ${cert.subject.CN}, your certificate was issued by ${cert.issuer.CN}!\n`)
} else {
res.writeHead(403);
res.end('Forbidden')
}
}).listen(8443);
console.log("Listening on :8443 ...");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment