Building an OpenSSL Certificate Authority - Creating ECC Certificates
Creating ECC Certificates
Previously on Building an OpenSSL CA, we created a certificate revocation list, OCSP certificate, and updated our OpenSSL configuration file to include revokation URI data. Now we are ready to create our first server certificate and sign them with our fully armed and operational CA. What's becoming a theme there are two caveats to note prior to creating our first server CSR. Stop rolling your eyes and stay with me.
- Certificates MUST have subjectAltName (SAN) extensions of type DNSName defined1.
- Openssl currently supports population of SubjectAltName through configuration files only, including the current version v1.1.0f (true at guides publication date)2.
Copy the Gist openssl_server.cnf file to
/root/ca/intermediate/openssl_server.cnf
and modify the contents for your own naming conventions. The openssl_server.cnf
file has new entries at the [server_cert]
location to create the subjectAltName
field our certificate mentioned in the earlier noted points. This alternative name should match what we enter for the [commonName]
field.
[ server_cert ] subjectAltName = @alt_names [alt_names] DNS.0 = webby.grilledcheese.us
You can add additional names to the certificate by iterating the [alt_names] section. Below is an example of the openssl config formatting for multiple names. Example:
[alt_names] DNS.0 = yourdomain.com DNS.1 = sassymolassy.yourdomain.com DNS.2 = *.skeletor.yourdomain.com DNS.3 = *.orco.greyskull.yourdomain.com
RFC 5280 regarding subject alternative names states no upper bound limit is defined (no limit to how many names you can enter). However there are practical and application limitations so plan your certificate's alternate names wisely and try to match what you would implement in production. You're also thinking, how does this scale for multiple CSRs? It doesn't. You'll need to either update the openssl_server.cnf every time you want to create a new certificate or create a copy for each new certificate. We'll worry about scripting and simplifying that process in another followup article.
Create the private key and CSR.
Create the private key and CSR and specify either P-256 or P-384 approved curves. Since the root and intermediary CA's use P-384, Suite B allows us to use either. If we created the CA using P-256, we would not be able to use P-384 for the client/server certificate. We also need to ensure our certificate's hash function matches the signing CA, in our case SHA-384.
# cd /root/ca # openssl req -config intermediate/openssl_server.cnf -new -newkey ec:<(openssl ecparam -name secp384r1) -keyout intermediate/private/webby.cheese.key.pem -out intermediate/csr/webby.cheese.csr Generating an EC private key writing new private key to 'intermediate/private/webby.cheese.key.pem' Enter PEM pass phrase: Verifying - Enter PEM pass phrase: ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [US]: State or Province Name [WA]: Locality Name [Seattle]: Organization Name [Grilled Cheese Inc.]: Organizational Unit Name [Grilled Cheese Dev Lab]: Common Name []:webby.grilledcheese.us Email Address [grilledcheese@yummyinmytummy.us]:
Create the Certificate
Use the intermediary certificate to create and sign the CSR for webby.grilledcheese.us.
# cd /root/ca # openssl ca -config intermediate/openssl_server.cnf -extensions server_cert -days 730 -in intermediate/csr/webby.cheese.csr -out intermediate/certs/webby.cheese.crt.pem Using configuration from intermediate/openssl_server.cnf Enter pass phrase for /root/ca/intermediate/private/int.cheese.key.pem: Check that the request matches the signature Signature ok Certificate Details: Serial Number: 4104 (0x1008) Validity Not Before: Sep 6 20:10:39 2017 GMT Not After : Sep 6 20:10:39 2019 GMT Subject: countryName = US stateOrProvinceName = WA localityName = Seattle organizationName = Grilled Cheese Inc. organizationalUnitName = Grilled Cheese Dev Lab commonName = webby.grilledcheese.us emailAddress = grilledcheese@yummyinmytummy.us X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Cert Type: SSL Server Netscape Comment: Grilled Cheese Generated Server Certificate X509v3 Subject Key Identifier: E0:48:57:7E:F9:92:BA:B9:F9:23:41:8D:3D:85:86:82:25:5C:FC:92 X509v3 Authority Key Identifier: keyid:7E:2D:A5:D0:9B:70:B9:E3:D2:F7:C0:0A:CF:70:9A:8B:80:38:B1:CD DirName:/C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Root CA/CN=Grilled Cheese Inc. Root Certificate Authority/emailAddress=grilledcheese@yummyinmytummy.us serial:10:01 X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication X509v3 CRL Distribution Points: Full Name: URI:http://crl.grilledcheese.us/whomovedmycheese.crl Authority Information Access: CA Issuers - URI:http://ocsp.grilledcheese.us/cheddarcheeseroot.crt OCSP - URI:http://ocsp.grilledcheese.us/ X509v3 Subject Alternative Name: DNS:webby.grilledcheese.us Certificate is to be certified until Sep 6 20:10:39 2019 GMT (730 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
Validate the certificate
# openssl x509 -noout -text -in intermediate/certs/webby.cheese.crt.pem Certificate: Data: Version: 3 (0x2) Serial Number: 4104 (0x1008) Signature Algorithm: ecdsa-with-SHA384 Issuer: C = US, ST = WA, O = Grilled Cheese Inc., OU = Grilled Cheese Intermediary CA, CN = Grilled Cheese Inc. Intermediary Certificate Authority, emailAddress = grilledcheese@yummyinmytummy.us Validity Not Before: Sep 6 20:10:39 2017 GMT Not After : Sep 6 20:10:39 2019 GMT Subject: C = US, ST = WA, L = Seattle, O = Grilled Cheese Inc., OU = Grilled Cheese Dev Lab, CN = webby.grilledcheese.us, emailAddress = grilledcheese@yummyinmytummy.us Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) pub: 04:bf:48:5b:9b:b2:e2:cf:de:e6:5a:33:3a:9f:73: 70:82:75:86:bd:6f:6a:98:e6:5e:31:fb:af:c5:9f: 68:dc:8b:bc:24:69:08:d8:35:c9:be:76:d4:3d:c5: 48:b3:8f:f6:fd:4a:b9:75:70:58:2c:65:f5:72:61: 62:b8:58:ae:ba:f1:cc:95:1e:bd:60:b2:18:92:19: d2:c3:fd:60:10:60:5a:ad:e5:29:94:f8:37:1b:5b: e5:41:50:fe:39:b9:1c ASN1 OID: secp384r1 NIST CURVE: P-384 X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Cert Type: SSL Server Netscape Comment: Grilled Cheese Generated Server Certificate X509v3 Subject Key Identifier: E0:48:57:7E:F9:92:BA:B9:F9:23:41:8D:3D:85:86:82:25:5C:FC:92 X509v3 Authority Key Identifier: keyid:7E:2D:A5:D0:9B:70:B9:E3:D2:F7:C0:0A:CF:70:9A:8B:80:38:B1:CD DirName:/C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Root CA/CN=Grilled Cheese Inc. Root Certificate Authority/emailAddress=grilledcheese@yummyinmytummy.us serial:10:01 X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication X509v3 CRL Distribution Points: Full Name: URI:http://crl.grilledcheese.us/whomovedmycheese.crl Authority Information Access: CA Issuers - URI:http://ocsp.grilledcheese.us/cheddarcheeseroot.crt OCSP - URI:http://ocsp.grilledcheese.us/ X509v3 Subject Alternative Name: DNS:webby.grilledcheese.us Signature Algorithm: ecdsa-with-SHA384 30:65:02:31:00:b1:ab:4e:4f:21:86:14:12:fe:34:ea:47:00: 67:29:cb:47:70:b2:ad:22:a0:dc:5b:65:7b:22:10:5e:ea:08: 7d:09:8d:c5:77:f5:8b:ff:fa:d2:5b:7a:1e:c6:57:e2:12:02: 30:64:f1:fb:14:ea:cf:b4:20:7d:f3:f5:bc:d0:82:0c:06:03: fc:05:84:5d:f9:37:dc:d6:51:83:7b:8b:f6:91:08:d6:22:4f: 16:96:ff:0a:52:68:47:09:0c:71:90:23:d4
Validation of the webby.cheese.crt.pem file shows the updated x509 fields that define our server certificate:
X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Cert Type: SSL Server Netscape Comment: Grilled Cheese Generated Server Certificate
The certificate also includes full CRL and OCSP endpoints.
X509v3 CRL Distribution Points: Full Name: URI:http://crl.grilledcheese.us/whomovedmycheese.crl Authority Information Access: CA Issuers - URI:http://ocsp.grilledcheese.us/cheddarcheeseroot.crt OCSP - URI:http://ocsp.grilledcheese.us/ And it includes our required subjectAltname. X509v3 Subject Alternative Name: DNS:webby.grilledcheese.us
The
index.txt
file we created for our intermediary certificate now has a new entry. Confirm the CA's database is updated with the newly created certificate. This file will prevent new certificates from being created with the same CN. If you need to recreate the certificate with the same name AND YOU'RE IN A LAB ENVIRONMENT, you can use vi/vim/nano/whatever to delete this line. The production-preferred method is to revoke and reissue.
# cat intermediate/index.txt V 180828222314Z 1007 unknown /C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Intermediary CA/CN=ocsp.grilledcheese.us/emailAddress=grilledcheese@yummyinmytummy.us V 190906201039Z 1008 unknown /C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Dev Lab/CN=webby.grilledcheese.us/emailAddress=grilledcheese@yummyinmytummy.us
The intermediary certificate was responsible for signing the OCSP certificate and our new server certificate; both are listed in the index.txt file. Lastly we can validate the entire certificate chain using the previously created chain.cheese.crt.pem against our newly created server certificate.
# openssl verify -CAfile intermediate/certs/chain.cheese.crt.pem intermediate/certs/webby.cheese.crt.pem intermediate/certs/webby.cheese.crt.pem: OK
Deploying Your Certificate
Your application or server will usually accept PEM format or a PFX bundle which contains certificate, key and certificate chain (if you desire to). In production environments you would not distribute the root certificate along with the intermediate. Even in lab environments, you should distribute the root certificate independently to clients to simulate real world environments. In production systems all mainstream certificate authorities are packaged with operating systems or independent key stores. The intermediary used should match one of these existing root CAs only... For our example, if you were deploying the PEM formatted files, you would need to provide:
- webby.cheese.key.pem (our server certificate's private key)
- webby.cheese.crt.pem (our server certificate)
- int.cheese.crt.pem or chain.cheese.crt.pem (our intermediary CA's certificate or root and certificate concatenated into one file)
If you plan to install the certificate and chain in PFX format:
# openssl pkcs12 -export -out intermediate/certs/webby.cheese.pfx -inkey intermediate/private/webby.cheese.key.pem -in intermediate/certs/webby.cheese.crt.pem -certfile intermediate/certs/chain.cheese.crt.pem Enter pass phrase for intermediate/private/webby.cheese.key.pem: ****** Enter Export Password: ****** Verifying - Enter Export Password: ******
Validate the PFX bundle
# openssl pkcs12 -info -in intermediate/certs/webby.cheese.pfx Enter Import Password: ****** MAC:sha1 Iteration 2048 PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048 Certificate bag Bag Attributes localKeyID: F7 6B 18 13 DD 04 4E 31 D7 A4 8D AE F5 1F 3B DC AD F3 F8 E8 subject=/C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Dev Lab/CN=webby.grilledcheese.us/emailAddress=grilledcheese@yummyinmytummy.us issuer=/C=US/ST=WA/O=Grilled Cheese Inc./OU=Grilled Cheese Intermediary CA/CN=Grilled Cheese Inc. Intermediary Certificate Authority/emailAddress=grilledcheese@yummyinmytummy.us -----BEGIN CERTIFICATE----- MIIFSDCCBM6gAwIBAgICEAgwCgYIKoZIzj0EAwMwgdIxCzAJBgNVBAYTAlVTMQsw .... lv8KUmhHCQxxkCPU -----END CERTIFICATE----- Certificate bag Bag Attributes: no attributes="" subject=/C=US/ST=WA/O=Grilled Cheese Inc./OU=Grilled Cheese Intermediary CA/CN=Grilled Cheese Inc. Intermediary Certificate Authority/emailAddress=grilledcheese@yummyinmytummy.us issuer=/C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Root CA/CN=Grilled Cheese Inc. Root Certificate Authority/emailAddress=grilledcheese@yummyinmytummy.us -----BEGIN CERTIFICATE----- MIID/TCCA4OgAwIBAgICEAEwCgYIKoZIzj0EAwMwgdQxCzAJBgNVBAYTAlVTMQsw .... wO2cWbcYwybr33gTaEdmtUM= -----END CERTIFICATE----- Certificate bag Bag Attributes: no attributes="" subject=/C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Root CA/CN=Grilled Cheese Inc. Root Certificate Authority/emailAddress=grilledcheese@yummyinmytummy.us issuer=/C=US/ST=WA/L=Seattle/O=Grilled Cheese Inc./OU=Grilled Cheese Root CA/CN=Grilled Cheese Inc. Root Certificate Authority/emailAddress=grilledcheese@yummyinmytummy.us -----BEGIN CERTIFICATE----- MIIDQTCCAsegAwIBAgIJAP+99S/FDT0CMAoGCCqGSM49BAMDMIHUMQswCQYDVQQG .... /kiTCl//67LTrlpoh9zJLFSNBGh/ -----END CERTIFICATE----- PKCS7 Data Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048 Bag Attributes localKeyID: F7 6B 18 13 DD 04 4E 31 D7 A4 8D AE F5 1F 3B DC AD F3 F8 E8 Key Attributes: no attributes="" Enter PEM pass phrase: Verifying - Enter PEM pass phrase: -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBEzBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQItDjLLd4ozIkCAggA .... GxO/udVd0Bg0zY6eSQV1xyXhGd4GJexnKv/IHeYWjpJMyNqa4O9o -----END ENCRYPTED PRIVATE KEY-----
We've completed building a two-tier NSA Suite B certificate authority for use within dev or lab environment. You'll still want to create web services to home the CRL list and act as OCSP Resolvers if you need that level of testing. The big drawback to manually using OpenSSL is the requirement of configuration files for
SAN
requirements. Manually updating or iterating a new OpenSSL configuration file for each certificate (requiring subjetAltName) is not efficient but I have yet to find a clean script to resolve this. I guess we'll just build one. Later.
Notes:
(1)The subjectAltName field was proposed to be preferred instead of the commonName (CN) field in RFC 2818 by Mozilla's E. Rescorla (who submitted it under his company RTFM, Inc... look up the acronym). No one really knew about it because the RFC also allowed defaulting back to the CN field if no subjectAltName existed. But combined with the seldom read CA/Browser forum's Baseline Requirements Certificate Policy for the Issuance and Management of Publicly-Trusted Certificates (released April of 2017), the subjectAltName field is now the only field of consequence for defining hostnames or IP's in a certificate. Guess how everyone found about this. Browsers simply removed support for the CN field as the host name and broke everyone's web sites siting "correcting a 17 year old requirement". Fortunately for some of us, our public CA's started auto-populating this field for a several years prior to the browser abandonment and reduced the impact to public sites. However internal CA's were left floundering (unless you read every RFC that comes out and then that doesn't even cover it). Thanks E. Rescorla for your vaugely worded RFC and Google's inability to provide visibility like they did to SHA1 deprecation (with advanced public warning and careful planning). Let's forget that the field is called ALTERNATE NAME... that annoys me at a core level. You have nothing better to do than read every RFC that could potentially affect your life, 17 years down the road... right?
(2) OpenSSL Git pull request #341 "Add 'copy and 'move configuration values for DNS Subject Alternative Names" exists in the Post 1.1.0 milestone but code commit is still pending into openssl:master branch. So we're stuck with config files for each certificate you want to use for now, unless you want to script it yourselves. Alternativly, OpenSSL has an GIT open Issue #3311 for "Interactivly specify subjecAltName (SAN). Here's to hoping.
- Noname1011Nimbostratus
For anyone needing a copy of openssl_server.cnf:
[ ca ] default_ca = CA_default [ CA_default ] # Directory and file locations. dir = /root/ca/intermediate certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/certs database = $dir/index.txt serial = $dir/serial RANDFILE = $dir/private/.rand # The root key and root certificate. private_key = $dir/private/int.cheese.key.pem certificate = $dir/certs/int.cheese.crt.pem # For certificate revocation lists. crlnumber = $dir/crlnumber crl = $dir/crl/whomovedmycheese.crl crl_extensions = crl_ext default_crl_days = 180 # SHA-1 is deprecated, so use SHA-2 or SHA-3 instead. default_md = sha384 name_opt = ca_default cert_opt = ca_default default_days = 3000 preserve = no policy = policy_loose [ policy_loose ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] # Options for the `req` tool (`man req`). default_bits = 2048 distinguished_name = req_distinguished_name string_mask = utf8only # SHA-1 is deprecated, so use SHA-2 or SHA-3 instead. default_md = sha384 # Extension to add when the -x509 option is used. x509_extensions = v3_ca [ req_distinguished_name ] countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name localityName = Locality Name 0.organizationName = Organization Name organizationalUnitName = Organizational Unit Name commonName = Common Name emailAddress = Email Address # Optionally, specify some defaults. countryName_default = US stateOrProvinceName_default = WA localityName_default = Seattle 0.organizationName_default = Grilled Cheese Inc. organizationalUnitName_default = Grilled Cheese Intermediary CA emailAddress_default = grilledcheese@yummyinmytummy.us [ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign crlDistributionPoints = @crl_info authorityInfoAccess = @ocsp_info [ usr_cert ] # Extensions for client certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [ server_cert ] # Extensions for server certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = server nsComment = "Grilled Cheese Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth crlDistributionPoints = @crl_info authorityInfoAccess = @ocsp_info subjectAltName = @alt_names [alt_names] DNS.0 = CN Name Here DNS.1 = Whatever else here [ crl_ext ] # Extension for CRLs (`man x509v3_config`). authorityKeyIdentifier=keyid:always [ ocsp ] # Extension for OCSP signing certificates (`man ocsp`). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning [crl_info] URI.0 = http://crl.grilledcheese.us/whomovedmycheese.crl [ocsp_info] caIssuers;URI.0 = http://ocsp.grilledcheese.us/cheddarcheeseroot.crt OCSP;URI.0 = http://ocsp.grilledcheese.us/