OpenSSL
OpenSSL needs no introduction.
Generating a Certificate Authority (CA) Using OpenSSL
- Replacing
-newkey ec -pkeyopt ec_paramgen_curve:prime256v1
with -newkey rsa:4096
to use RSA key.
- Full Subject options are
/C=County/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname
.
1
2
3
4
5
|
openssl req -x509 -nodes -days 365 \
-newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-keyout ca.key -out ca.crt \
-subj "/O=Zeng/CN=CA" \
-addext "keyUsage=critical, keyCertSign, cRLSign"
|
You can utilize the generated CA to sign certificates.
1
2
3
4
5
6
7
8
9
10
11
12
|
openssl req -new -nodes \
-newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-keyout kube-apiserver.key -out kube-apiserver.csr \
-subj "/O=system:masters/CN=kube-apiserver" \
-addext "basicConstraints=critical,CA:FALSE" \
-addext "keyUsage=digitalSignature,keyEncipherment" \
-addext "extendedKeyUsage=serverAuth" \
-addext "subjectAltName=DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local,DNS:localhost,IP:127.0.0.1"
openssl x509 -req -sha256 -days 3650 -copy_extensions=copy \
-in kube-apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out kube-apiserver.crt
|
For versions of OpenSSL prior to v3.0.0, you should generate the CSR and certificate like below. Please refer to the discussion Missing X509 extensions with an openssl-generated certificate.
1
2
3
4
5
6
7
8
9
|
openssl req -new -nodes \
-newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-subj "/O=system:masters/CN=kube-apiserver" \
-keyout kube-apiserver.key -out kube-apiserver.csr
openssl x509 -req -sha256 -days 3650 \
-in kube-apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out kube-apiserver.crt -extensions v3_req \
-extfile <(printf "[v3_req]\nbasicConstraints=critical,CA:FALSE\nkeyUsage=digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth\nsubjectAltName=DNS:localhost,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local,IP:127.0.0.1")
|
Full options can be found at OpenSSL x509v3_config.
CFSSL
CFSSL is CloudFlare’s PKI/TLS swiss army knife.
It is both a command line tool and an HTTP API server for signing, verifying, and bundling TLS certificates.
CFSSL is more easier than OpenSSL.
Option groups can be pre-defined in CA config, and reused to generate TLS certificates numbers of components in large system.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
{
cat > ca-csr.json <<EOF
{
"CN": "Kubernetes",
"key": {
"algo": "ecdsa",
"size": 521
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "CA",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
}
|
The ca-config.json
file, particularly the profiles section, can be reused as template to issue series of certificates.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOF
|
Next we use root CA to issue a certificate, with profile kubernetes
and other default configs in ca-config.json
defined previously.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
{
cat > admin-client.json <<EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:masters",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare admin
}
|
Programmatic Way
Using Golang as an exmaple. (One of Rust example is est31/rcgen).
Golang std crypto/tls/generate_cert.go provides a simple way to generate self-signed certificate.
host
configures the Subject Alternative Name
(SAN). SAN
is an extension to the X.509 specification that allows users to specify additional identities for a single SSL certificate. Defined options include an email address, a DNS name, an IP address, and a uniform resource identifier (URI).
ca
configures whether this cert should be its own Certificate Authority
ecdsa-curve
is ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521
rsa-bits
is Size of RSA key to generate. Ignored if –ecdsa-curve is set
It can be compile to binary by go build generate_cert.go
so as to use as command tool.
The output certificate have fix Issuer: O=Acme Co
and Subject: O=Acme Co
(useful in some scope, like mTLS). Changing the code and making it as arguments overcome this shortcoming.
It is very suitable for the following cases:
- testing
- webhook plugin: large system such as Kubernetes requires that the webhook server must use the HTTPS protocol
It is not suitable for complex scenarios, such as generating certificate chains.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
$ wget https://raw.githubusercontent.com/golang/go/master/src/crypto/tls/generate_cert.go
# replace --ecdsa-curve P256 with --rsa-bits 2048 to generate RSA key
$ go run generate_cert.go --host example.com,127.0.0.1,::1 --ecdsa-curve P256 --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
2022/07/06 17:57:16 wrote cert.pem
2022/07/06 17:57:16 wrote key.pem
$ openssl x509 -in cert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
b0:01:ee:99:c9:29:f7:50:25:29:12:e4:c8:7e:17:c4
Signature Algorithm: ecdsa-with-SHA256
Issuer: O=Acme Co
Validity
Not Before: Jan 1 00:00:00 1970 GMT
Not After : Jan 29 16:00:00 2084 GMT
Subject: O=Acme Co
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:70:da:c2:1e:02:ac:d7:23:0c:53:cc:f2:70:df:
30:3f:16:e5:fd:ce:18:b6:48:9f:02:e4:25:29:54:
5b:07:8c:1e:92:cd:25:94:f7:81:e3:fe:76:8c:b0:
26:84:49:8c:92:3e:85:1e:0e:bf:21:bd:4a:95:a7:
71:ed:b4:db:fb
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Certificate Sign
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
7F:7C:6F:06:36:E3:E9:E7:8D:12:69:BB:E5:F5:4B:4C:C4:8D:B8:D8
X509v3 Subject Alternative Name:
DNS:example.com, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
Signature Algorithm: ecdsa-with-SHA256
30:45:02:20:15:e2:32:3c:47:ff:a5:fc:00:83:cf:e3:4c:60:
7d:2e:51:26:0a:bd:b3:44:ba:08:f6:3b:e4:79:62:63:c4:d6:
02:21:00:b7:62:55:e4:b0:19:f0:7f:ad:60:b2:bf:dc:73:09:
2f:02:9a:5d:dc:58:8b:99:79:69:de:be:34:3e:74:3e:20
|
Further Reading
- X.509 specification
- OpenSSL x509v3_config
- Introducing CFSSL - CloudFlare’s PKI toolkit
- kubernetes-the-hard-way/Provisioning a CA and Generating TLS Certificates
- cfssl 核心模块分析
- Golang std crypto/tls/generate_cert.go
- est31/rcgen
Author
Zeng Xu
LastMod
2023-05-01 14:16
License
本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,转载时请注明原文链接。