Basic Crypto Operations Using step
Description
You don't need to run an online Certificate Authority to create certificates and perform basic crypto operations using the step
CLI tool. This document gives some examples of things you can do with the step
command by itself.
Overview
Here's a few common uses of the step
command:
- Create and work with X.509 certificates
- Get a TLS Certificate From Let's Encrypt
- Generate JSON Web Tokens (JWTs) and JSON Web Keys (JWKs)
- Obtain and Work With OAuth Tokens
- Miscellaneous Tools (TOTP Tokens, NaCl, SSH Certificates)
Requirements
Create and work with X.509 certificates
Let's take a look at the step certificate
command group.
This command group is a Swiss Army knife for working with certificates.
You can use it to create certificate signing requests (CSRs),
sign CSRs,
create self-signed certificates (e.g., a root certificate authority),
create leaf or intermediate CA certificates,
validate and inspect certificates,
renew certificates,
generate certificate bundles,
and to key-wrap private keys.
Shall we try it out?
Create a Certificate Authority
Create a Root CA:
step certificate create --profile root-ca "Example Root CA" root_ca.crt root_ca.key
Typically you will also want an intermediate CA. Create an Intermediate CA that is signed by your Root CA:
step certificate create "Example Intermediate CA 1" \
intermediate_ca.crt intermediate_ca.key \
--profile intermediate-ca --ca ./root_ca.crt --ca-key ./root_ca.key
Now you can store your root_ca.key
in a safe place offline, because you'll only need the intermediate CA key to issue TLS leaf certificates.
Issue a Leaf Certificate Bundle
Use your intermediate CA to sign leaf (end entity) certificates for your servers.
Create a leaf TLS certificate for example.com
, valid for a year:
step certificate create example.com example.com.crt example.com.key \\
--profile leaf --not-after=8760h \\
--ca ./intermediate_ca.crt --ca-key ./intermediate_ca.key --bundle
By using the --bundle
flag we automatically bundle the new leaf certificate
with the signing intermediate certificate. TLS-based services will require the
bundle in order to verify the full chain.
$ step certificate verify example.com.crt --roots root_ca.crt
(no output - certificate is valid)
Inspect an X.509 Certificate
To inspect the certificate you just made, run:
$ step certificate inspect example.com.crt --short
Subject: example.com
Issuer: Example Intermediate CA 1
Valid from: 2020-09-02T20:48:41Z
to: 2021-09-02T20:48:40Z
You can get a certificate in JSON format by calling step certificate inspect
with --format json
. This example uses jq to parse the JSON and extract a specific value:
$ step certificate inspect example.com.crt --format json | jq -r .validity.end
2020-09-03T20:48:41Z
You can also inspect the TLS certificate for any URL:
$ step certificate inspect https://smallstep.com --format json | jq -r .validity.end
2020-11-13T07:09:47Z
Get a TLS Certificate From Let's Encrypt
step
is a full-fledged ACME client (the protocol used by Let's Encrypt. Unlike other ACME clients, step
connects to a configured step-ca
daemon by default. To use it with Let's Encrypt or another ACME server instead, you can pass an --acme
endpoint:
step ca certificate example.com example.com.crt example.com.key \
--acme https://acme-v02.api.letsencrypt.org/directory
This command will:
- Request a SSL certificate from Let's Encrypt and receive a challenge token in response
- Start up a standalone HTTP server on port 80 that serves the
http-01
challenge response at/.well-known/acme-challenge/<TOKEN>
. - Wait for Let's Encrypt to hit the HTTP server and issue a certificate
- Save the certificate and private key to
example.com.crt
andexample.com.key
If you don't want step
to run a standalone server to respond to the ACME challenge, you can pass --webroot <path>
to specify a path where step
will place the .well-known/acme-challenge/<TOKEN>
token file.
For a dry run, you can use Let's Encrypt's staging server URL: https://acme-staging-v02.api.letsencrypt.org/directory
Generate JSON Web Tokens (JWTs) and JSON Web Keys (JWKs)
The following command groups work with JOSE objects like JWTs and JWEs:
In this example, you'll create a JSON Web Key (JWK), add the public key to a keyset, and sign a JSON Web Token (JWT) that expires in 15 minutes:
$ step crypto jwk create pub.json key.json
$ cat pub.json | step crypto jwk keyset add keys.json
$ JWT=$(step crypto jwt sign \
--key key.json \
--iss "issuer@example.com" \
--aud "audience@example.com" \
--sub "subject@example.com" \
--exp $(date -v+15M +"%s"))
We can then verify the JWT and return the payload:
$ echo $JWT | step crypto jwt verify --jwks keys.json --iss "issuer@example.com" --aud "audience@example.com"
{
"header": {
"alg": "ES256",
"kid": "pwNr_RwEMFPxxfpUgsSHcCEP-CVIFQ_maI9UiHljqt0",
"typ": "JWT"
},
"payload": {
"aud": "audience@example.com",
"exp": 1599086725,
"iat": 1599085826,
"iss": "issuer@example.com",
"jti": "5681b0ad0e624c2c6da4ad610e298ba4f54c2e0c8f2731698b214126c5e780c9",
"nbf": 1599085826,
"sub": "subject@example.com"
},
"signature": "wco1X1ue14D9wmgH_DXIbTZXIg_McXRMlV80O1JDPo12j8zhHIWQikYxUBvbxfME2VbNO5WRKUB9H9WjX2FlnQ"
}
Obtain and Work With OAuth Tokens
The step oauth
command group supports API authorization and single sign on with OAuth and OIDC.
This command group requires that you supply your own OAuth provider URL, client ID, and client secret.
Obtain OAuth OIDC Identity Tokens
In this example, we'll sign into Google and get an OIDC identity token. Replace the --client-id
and --client-secret
with your own values obtained from Google Cloud Console's APIs & Services menu.
$ TOKEN=$(step oauth \
--provider https://accounts.google.com \
--client-id 1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com \
--client-secret udTrOT3gzrO7W9fDPgZQLfYJ \
--bare --oidc)
The --provider
URL must have a discovery endpoint, created by appending /.well-known/openid-configuration
to the URL. This is a JSON file describing endpoints and keys for OpenID Connect. For example, see https://accounts.google.com/.well-known/openid-configuration
.
Once you have an OIDC identity token, you can verify it. The --jwks
value comes from the jwks_uri
value at the OpenID discovery endpoint.
$ echo $TOKEN | step crypto jwt verify \
--jwks https://www.googleapis.com/oauth2/v3/certs \
--iss https://accounts.google.com \
--aud 1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com
Miscellaneous Tools (TOTP Tokens, NaCl, SSH Certificates)
Generate TOTP Tokens for Multi-Factor Authentication (MFA)
With step crypto otp
, you can generate a TOTP token and a QR code:
step crypto otp generate \
--issuer smallstep.com --account name@smallstep.com \
--qr smallstep.png > smallstep.totp
Scan the QR Code using Google Authenticator, Authy, or similar software and use it to verify the TOTP token:
step crypto otp verify --secret smallstep.totp
Sign and Encrypt Arbitrary Data
You can use the step crypto nacl
command group to sign or encrypt arbitrary data for internal use. This command group uses the NaCl library's high-speed crypto primitives.
Work with SSH Certificates
The step ssh
command group is usually used in conjunction with step-ca
's SSH CA functionality. But not all the subcommands require an SSH CA. You can inspect an SSH certificate:
$ step ssh inspect < mycert.crt
-:
Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate
Public key: ECDSA-CERT SHA256:5Zu0dV5Q0DLtXTBs6UWtvNNzg1gqUVTfvogzKyPcKPs
Signing CA: ECDSA SHA256:PxHk36T6v70LP+wfD/RB1IbmA9I4EpyLq72F0eOH5hE
Key ID: "carl@example.com"
Serial: 2937319031419699911
Valid: from 2020-09-08T17:07:53 to 2020-09-09T09:08:53
Principals:
carl
carl@example.com
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rc
And you can get the fingerprint of an SSH certificate or public key:
$ step ssh fingerprint < mycert.crt
256 SHA256:CQ6+r7ccb/wqoWK1ror10c44nNvvYXp2mgbPrsTmCbw c (ECDSA-CERT)