How to create and import a root CA key and certificate onto multiple YubiKeys (for backup / cold storage purposes), and use the root CA to sign a new intermediate CA on a different YubiKey that will be used with step-ca for online leaf certificate signing.
You will need:
- ykman
- step
- step-kms-plugin
- At least three YubiKeys with PIV support. One will be used for an online intermediate CA, and the rest will be for offline root CA backups.
First, on an airgapped machine, generate a key pair on disk:
$ step crypto keypair root.pub root.priv --kty EC --curve P-384 --insecure --no-password
$ cat root.priv
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAF2rMNn98KPhH8VDr3HvyMAjSghnMkhTOSL0piQaiAKEOYJ1tvuudy
ADG1WKuc5ZegBwYFK4EEACKhZANiAAStX74Q9vp5yjA98r8tUo6bVVpjpYEQ5eu5
G5v8XGniFnxoKSibEykLz9sF8u1Yy7yba7rrxiu0/Y8KXatWRNSZ8DjtgX3ZivyD
+woDjW0+1zVf5eBs8lWqHkzpA5BNN84=
-----END EC PRIVATE KEY-----
$ cat root.pub
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAErV++EPb6ecowPfK/LVKOm1VaY6WBEOXr
uRub/Fxp4hZ8aCkomxMpC8/bBfLtWMu8m2u668YrtP2PCl2rVkTUmfA47YF92Yr8
g/sKA41tPtc1X+XgbPJVqh5M6QOQTTfO
-----END PUBLIC KEY-----
Generate a Root CA certificate:
$ step certificate create --profile root-ca "Smallstep Root CA" root_ca.crt --key root.priv
Your certificate has been saved in root_ca.crt.
For each root YubiKey, insert the key and run the following:
$ ykman piv keys import 82 root.priv
$ ykman piv certificates import 82 root_ca.crt
Your root CA has been backed up and you can now delete the private key:
$ shred -u root.priv
Let's now make an online intermediate CA. Switch to the Yubikey that you'll use for your online CA.
$ step kms create --crv P384 --touch-policy NEVER --kms 'yubikey:pin-value=123456' 'yubikey:slot-id=83' > intermediate.pub
$ cat intermediate.pub
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE5wGsd5nT74PhNpcToJMADrYF5DDSd3UT
geBDkLknghyhKVAZhpbRXUKRbj7C3aErYtbOUfVxiK5puln9EgWOgyEFI5ziwXI5
QTuvLHaR/W/oYA1Rj4ok8Qd7wbNg/nFh
-----END PUBLIC KEY-----
$ ykman piv certificates request 83 intermediate.pub intermediate.csr -s "Smallstep Intermediate CA"
$ step certificate inspect intermediate.csr
Certificate Request:
Data:
Version: 0 (0x0)
Subject: CN=Smallstep Intermediate CA
Subject Public Key Info:
Public Key Algorithm: ECDSA
Public-Key: (384 bit)
X:
ad:5f:be:10:f6:fa:79:ca:30:3d:f2:bf:2d:52:8e:
9b:55:5a:63:a5:81:10:e5:eb:b9:1b:9b:fc:5c:69:
e2:16:7c:68:29:28:9b:13:29:0b:cf:db:05:f2:ed:
58:cb:bc
Y:
9b:6b:ba:eb:c6:2b:b4:fd:8f:0a:5d:ab:56:44:d4:
99:f0:38:ed:81:7d:d9:8a:fc:83:fb:0a:03:8d:6d:
3e:d7:35:5f:e5:e0:6c:f2:55:aa:1e:4c:e9:03:90:
4d:37:ce
Curve: P-384
Signature Algorithm: ECDSA-SHA256
30:65:02:30:55:21:ac:f9:4f:3a:b3:a8:0a:0a:f3:f0:a0:0a:
15:08:6b:54:eb:8e:82:18:cb:2e:35:c4:ee:bb:0f:b6:b6:4c:
b0:f6:68:fc:e3:1b:70:0f:a0:40:0b:57:a2:c4:77:20:02:31:
00:e3:13:14:b3:ee:92:58:7e:40:84:1e:f0:dc:fb:ac:7d:9c:
96:e8:09:a8:0a:e0:8b:35:9f:24:34:07:ed:b4:0b:6e:5e:a2:
22:ab:dd:f1:39:03:87:0c:6b:4d:f8:25:1c
Now switch back to a root CA Yubikey, to sign the CSR for the intermediate:
$ step certificate sign --profile intermediate-ca --kms 'yubikey:pin-value=123456' intermediate.csr root_ca.crt 'yubikey:slot-id=82' > intermediate_ca.crt
$ step certificate inspect intermediate_ca.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 29359969139228600868301666524100743019 (0x1616863d51a51a4d447edd37ebb6cf6b)
Signature Algorithm: ECDSA-SHA384
Issuer: CN=Smallstep Root CA
Validity
Not Before: Oct 19 21:06:56 2023 UTC
Not After : Oct 16 21:06:56 2033 UTC
Subject: CN=Smallstep Intermediate CA
Subject Public Key Info:
Public Key Algorithm: ECDSA
Public-Key: (384 bit)
X:
ad:5f:be:10:f6:fa:79:ca:30:3d:f2:bf:2d:52:8e:
9b:55:5a:63:a5:81:10:e5:eb:b9:1b:9b:fc:5c:69:
e2:16:7c:68:29:28:9b:13:29:0b:cf:db:05:f2:ed:
58:cb:bc
Y:
9b:6b:ba:eb:c6:2b:b4:fd:8f:0a:5d:ab:56:44:d4:
99:f0:38:ed:81:7d:d9:8a:fc:83:fb:0a:03:8d:6d:
3e:d7:35:5f:e5:e0:6c:f2:55:aa:1e:4c:e9:03:90:
4d:37:ce
Curve: P-384
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
DC:5E:5B:91:EF:E1:42:9F:FE:D9:66:2B:42:ED:51:97:3E:8D:3A:86
X509v3 Authority Key Identifier:
keyid:DC:5E:5B:91:EF:E1:42:9F:FE:D9:66:2B:42:ED:51:97:3E:8D:3A:86
Signature Algorithm: ECDSA-SHA384
30:64:02:30:48:8a:a0:d9:74:ba:f5:1a:a0:bf:ee:93:2b:78:
43:5d:2c:d1:d1:f1:02:0e:ac:02:85:8a:ff:f1:bd:4d:5c:a9:
4f:17:62:46:57:8e:a6:74:5f:b2:4e:70:c3:d5:22:03:02:30:
25:77:e7:cd:13:3d:4f:46:21:cb:e8:75:12:cd:26:80:38:d4:
d8:61:af:44:86:7e:2c:38:a7:ae:0c:df:6d:4b:c2:38:89:21:
be:1c:c0:9e:3f:3c:f3:eb:14:58:bf:14
Finally, return to the intermediate CA yubikey to import the intermediate certificate:
$ ykman piv certificates import 83 intermediate_ca.crt
Now, for your CA config, you'll want to use:
{
"root": "/etc/step-ca/certs/root_ca.crt",
"crt": "/etc/step-ca/certs/intermediate_ca.crt",
"key": "yubikey:slot-id=83",
"kms": {
"type": "yubikey",
"uri": "yubikey:management-key=01020304...?pin-value=123456"
}
}