How to setup your own CA with OpenSSL

For educational reasons I've decided to create my own CA. Here is what I learned.

First things first

Lets get some context first.

Public Key Cryptography

AKA asymmetric cryptography solves the problem of two entities communicating securely without ever exchanging a common key, by using two related keys, one private, one public.

Ciphered text with the public key can only be deciphered by the corresponding private key, and verifiable signatures with the public key can only be created with the private key.

But if the two entities do not know each other yet they a way to know for sure that a public key corresponds to the private key of the other identity.

In other words, when Alice speaks to Bob, Bob tells Alice "this is my public key K, use it to communicate with me" Alice needs to know it is really Bob's public key and not Eve's.

The usual solution to this problem is to use a PKI.

Public Key Infrastructure - PKI

A PKI is an arrangement that binds public keys to identities by means of a Certificate Authority (CA).

A CA is a centralized trusted third party whose public key is already known.

This way when Alice speaks to Bob, Bob shows Alice a signed message by Trent, who Alice knows and trusts, that says "this public key K belongs to Bob". That signed message is called a certificate, and it can contain other info. Alice is able to verify the signature using Trent's public key, and can know speak confidently to Bob.

It is also common to have a chain of trust. Alice speaks to Bob, Trent does not know Bob but knows Carol who knows Bob, so Bob shows Alice a chain of certificates, one from Carol that says which key belongs to Bob and one from Trent who says which key belongs to Carol. Even without knowing Carol, Alice can verify the certificate from Trent, be sure of Carol's key, and if her trust in Trent is transitive then she can also trust Carol as to who Bob is.

Note:
There is an interesting solution for public authentication of public-key information is the web-of-trustscheme, which uses third party attestations of self-signed certificates.

X.509

X.509 is a standard from the International Telecommunication Union for PKI.

Among other things, it defines the format for public key certificates.

Defined over these RFCs:

  • Version 1 - RFC1422

  • Version 2 - RFC2459

  • Version 3 - RFC5280

A X.509 v3 digital certificate has this structure:

  • Certificate

    • ...

    • Not Before

    • Not After

    • Version

    • Serial Number

    • Algorithm ID

    • Issuer

    • Validity

    • Subject

    • Subject public key info

    • Issuer Unique Identifier (optional)

    • Subject Unique Identifier (optional)

    • Extensions (optional)

    • Certificate Signature Algorithm

    • Certificate Signature

    Version, Serial, Algorithm ID and Validity

    • Version - Indicates X.509 version. Should be 3 (value 0x2).

    • Serial - Unique positive integer assigned by the CA to each certificate.

    • Algorithm ID - Must be the same as the field "Certificate Signature Algorithm"

    • Validity - Two dates that form the period when the certificate is valid.

    Issuer and Subject

    Each a Distinguished Name (DN), unique per CA.

    A DN, described in RFC1779, consists of a single line with these separated values:

    • CN - CommonName

    • L - LocalityName

    • ST - StateOrProvinceName

    • O - OrganizationName

    • OU - OrganizationalUnitName

    • C - CountryName

    Example:
    C=PT, ST=Lisboa, L=Lisboa, O=Foo Org, OU=Bar Sector, CN=foo.org/[email protected]

    The signing CA may not require all values.

    When connecting to an HTTPS server, browsers will check the CN value and it should be conforming to the domain. Wildcard certificates usually start with a * in CN to allow any subdomain. e.g.CN=*.example.com

    Note that browsers will reject the wilcard for the naked domain, i.e. example.com is not conforming to*.example.com.

    However, a certificate can be used for an HTTPS server that replies in multiple different domains. Additional domains can be specified in the extension Subject Alternative Names.

    Subject public key info

    Contains the public key algorithm and its specific parameters. e.g.:

    • algorithm: rsa encryption

    • key size: 2048

    • exponent: 0x10001

    • modulus: 00:ec:82:3f:78:b6...

    Issuer and Subject Unique Identifiers

    Introduced in version 2 to permit the reuse of issuer and subject names. For example, suppose a CA goes bankrupt and its name is deleted from the country's public list, after some time another CA with the same name may register itself even though it is unrelated to the first one.

    IMO, this is all very silly. Unsurprisingly, IETF recommends that no issuer and subject names be reused.

    Extensions

    Introduced in version 3. A CA can use extensions to issue a certificate only for a specific purpose, e.g only for http servers.

    Extensions can be critical or non-critical. Non-critical can be ignored, while critical must be enforced and the whole certificate must be rejected if the system does not recognize a critical extension.

    Some standard extensions:

    • Subject Key Identifier

    • Authority Key Identifier

    • Subject Alternative Name

    • Basic Constraints

    Authority and Subject Key Identifiers

    Used where an entity has multiple signing keys. Identity can be verified by either name and serial number or by this key identifier.

    An identifier is the 160-bit SHA-1 hash of the public key, or just the first 60 bits preceded with the bits 0100.

    Subject Alternative Name

    May contain additional DNS names or IP addresses where the certificate is valid, that is, besides the one specified in CN.

    Basic Constraints

    Whether the subject is a CA and optionally the maximum length of depth of certification paths.

    A real world need

    Let's suppose we need a signed certificate for an HTTPS server. This means we need a certificate for the domain (or domains) where the server will be available.

    We need a certificate that the browser can verify and tell the user that he is on the right servers of the domain of the URL he typed and that a safe connection is established.

    Browsers use a certificate store which has a list of CAs. To check your you can go to your browser's settings, search for the Certificates section, maybe in Security or Advanced, there should be some kind of certificate manager.

    The browser's certificate store should have several sections, one of them, probably empty is for client certificates, since HTTPS can also authenticate the client through certificates, although this isn't used except for some very specific corporate environments. The section you want to look at is the 'Authorities' section where the CA certificates are stored. Your browser most probably has certificates from VeriSign, Comodo, GeoTrust, Microsoft, etc.

    So what we need is a certificate that says our key belongs to our domain issued (signed) by one of these entities. Or we can also have it issued by an intermediary entity, one who was authorized by one of the CAs to issue certificates.

    If you do a web search for 'SSL Certificates' you'll find many sellers of digital certificates. You'll find that "wildcard" certificates are usually a bit more expensive.

    Wildcard certificates

    A wildcard certificate is a certificate which can be used with multiple subdomains of a domain.

    Browsers look for the CN (Common Name) in the subject field which should be a domain, or a wildcard like *.example.com.

    Browsers will accept a certificate with CN *.example.org for www.example.orglogin.example.org orbo.example.org. But the "naked" domain example.org will not work.

    Additional domains (including the naked domain) may be added in the extension "SubjectAltName".

    To check this out point your browser to https://mozilla.org (or some other HTTPS server), then click the lock icon before the URL, there should be a way to see the certificate being used. Check the subject Common Name and the extension Subject Alt Name.

    OpenSSL

    OpenSSL is a cryptography toolkit. Contains many subcommands, each with a manpage of its own e.g. ca(1)req(1) , x509(1).

    Most of OpenSSL's tools deal with -in and -out parameters. Usually you can also inspect files by specifying -in <file> and -noout, you also specify which part of the contents you're interested in, to see all use -text. Examples below.

    Generate Keys and Certificate Signing Request (CSR)

    Generate an RSA key for the CA:

    $ openssl genrsa -out example.org.key 2048 Generating RSA private key, 2048 bit long modulus .........................................+++

    openssl genrsa is the tool to generate rsa keys. 2048 is the key size. This created a file ca.key that contains the private key.

    You can use the tool openssl rsa to inspect the key.

    $ openssl rsa -in example.org.key -noout -text Private-Key: (2048 bit) modulus:     00:ad:d8:71:1f:ab:a7:df:a6:c3:7e:d8:1f:fd:81:     b0:5a:a8:9d:51:2b:15:c2:98:95:9e:fe:3b:7c:bd:     ... publicExponent: 65537 (0x10001) privateExponent:     7b:a9:ba:96:b7:c9:bb:eb:69:a7:62:60:27:39:c8:     d4:44:9b:5b:b0:d5:52:ce:ad:a8:22:da:f8:19:c2:     ... prime1:     00:d3:98:05:f5:49:48:11:f1:46:71:09:6c:b4:cb:     e6:3e:6f:a1:41:9a:36:43:c3:22:20:06:d1:aa:dd:     ... prime2:     00:d2:54:5e:cc:15:72:3d:5f:b2:64:ab:4f:42:a6:     15:79:ca:7a:e0:ef:dd:a7:f3:25:f2:f1:75:b2:33:     ... exponent1:     02:bf:5f:9c:6e:c6:2b:cd:79:3f:b0:82:a3:da:5d:     f4:03:99:11:74:02:2e:61:13:49:5d:2d:4d:cd:b1:     ... exponent2:     79:6c:c1:e9:9a:3c:00:98:9d:b9:a6:78:b4:a6:83:     61:73:76:ab:23:6f:58:c5:73:d4:24:77:e9:30:10:     ... coefficient:     17:53:93:4a:48:b0:63:9a:71:0e:37:fb:18:ad:be:     4e:d0:6e:af:6c:bc:7b:ff:44:c6:93:9a:23:03:51:     ...

    Optionally, the rsa public key can be extracted from the private key:

    $ openssl rsa -in example.org.key -pubout -out example.org.pubkey $ openssl rsa -in example.org.pubkey -pubin -noout -text Public-Key: (2048 bit) Modulus:     00:ad:d8:71:1f:ab:a7:df:a6:c3:7e:d8:1f:fd:81:     b0:5a:a8:9d:51:2b:15:c2:98:95:9e:fe:3b:7c:bd:     ... Exponent: 65537 (0x10001)

    Any copy of the private key should only be help by the entity who is going to be certified. This means the key should never be sent to anyone else, including the certificate issuer.

    We now generate a Certificate Signing Request which contains some of the info that we want to be included in the certificate. To prove ownership of the private key, the CSR is signed with the subject's private key.

    Generate a CSR:

    $ openssl req -new -key example.org.key -out example.org.csr 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) [AU]:PT State or Province Name (full name) [Some-State]:Lisboa Locality Name (eg, city) []:Lisboa Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Org Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:*.example.org Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:

    We can then take a look at the CSR's contents:

    $ openssl req -in example.org.csr -noout -text Certificate Request:     Data:         Version: 0 (0x0)         Subject: C=PT, ST=Lisboa, L=Lisboa, O=Example Org, CN=*.example.org         Subject Public Key Info:             Public Key Algorithm: rsaEncryption                 Public-Key: (2048 bit)                 Modulus:                     00:ad:d8:71:1f:ab:a7:df:a6:c3:7e:d8:1f:fd:81:                     b0:5a:a8:9d:51:2b:15:c2:98:95:9e:fe:3b:7c:bd:                     ...                 Exponent: 65537 (0x10001)         Attributes:             a0:00     Signature Algorithm: sha1WithRSAEncryption          5d:f0:d4:d8:85:4c:e7:dd:6d:f2:bd:05:0f:57:8b:d8:0a:40:          09:10:ad:ab:cc:5b:a1:92:cb:5d:56:16:7f:0b:23:91:32:06:          ...

    The certificate is then sent to the issuer, and if he approves the request a certificate should be sent back.

    Make sure your Signature Algorithm is not MD5. Old OpenSSL configurations have default_md = md5as default. Browsers reject certificates that use md5 as a signature algorithm because it has beenfound to be insecure.

    Notice that there are no extensions, to add extensions an additional config file is needed. This makes the process a bit more complicated so when you buy a wildcard certificate you don't usually need to specify the extension SubjectAltName for the naked domain because the issuer will do it for you.

    This is an example configuration file for a CSR:

    # The main section is named req because the command we are using is req # (openssl req ...) [ req ] # This specifies the default key size in bits. If not specified then 512 is # used. It is used if the -new option is used. It can be overridden by using # the -newkey option.  default_bits = 2048 # This is the default filename to write a private key to. If not specified the # key is written to standard output. This can be overridden by the -keyout # option. default_keyfile = oats.key # If this is set to no then if a private key is generated it is not encrypted. # This is equivalent to the -nodes command line option. For compatibility # encrypt_rsa_key is an equivalent option.  encrypt_key = no # This option specifies the digest algorithm to use. Possible values include # md5 sha1 mdc2. If not present then MD5 is used. This option can be overridden # on the command line. default_md = sha1 # if set to the value no this disables prompting of certificate fields and just # takes values from the config file directly. It also changes the expected # format of the distinguished_name and attributes sections. prompt = no # if set to the value yes then field values to be interpreted as UTF8 strings, # by default they are interpreted as ASCII. This means that the field values, # whether prompted from a terminal or obtained from a configuration file, must # be valid UTF8 strings. utf8 = yes # This specifies the section containing the distinguished name fields to # prompt for when generating a certificate or certificate request. distinguished_name = my_req_distinguished_name # this specifies the configuration file section containing a list of extensions # to add to the certificate request. It can be overridden by the -reqexts # command line switch. See the x509v3_config(5) manual page for details of the # extension section format. req_extensions = my_extensions [ my_req_distinguished_name ] C = PT ST = Lisboa L = Lisboa O  = Oats In The Water CN = *.oats.org [ my_extensions ] basicConstraints=CA:FALSE subjectAltName=@my_subject_alt_names subjectKeyIdentifier = hash [ my_subject_alt_names ] DNS.1 = *.oats.org DNS.2 = *.oats.net DNS.3 = *.oats.in DNS.4 = oats.org DNS.5 = oats.net DNS.6 = oats.in

    Notice the various DNS names. Since the configuration parser does not allow multiple values for the same name we use the @my_subject_alt_names and DNS.# with different numbers.

    With this configuration we can create a CSR with the proper extensions:

    $ openssl req -new -out oats.csr -config oats.conf Generating a 2048 bit RSA private key .............+++ ....................................+++ writing new private key to 'oats.key' -----

    Because we did not specify a key, OpenSSL uses the information on our configuration (default_bitsand default_keyfile) to create one.

    Lets see the result:

    $ openssl req -in oats.csr -noout -text Certificate Request:     Data:         Version: 0 (0x0)         Subject: C=PT, ST=Lisboa, L=Lisboa, O=Oats In The Water, CN=*.oats.org         Subject Public Key Info:             Public Key Algorithm: rsaEncryption                 Public-Key: (2048 bit)                 Modulus:                     00:a2:58:fc:57:32:4d:40:aa:62:92:65:86:1d:6b:                     4f:3e:11:a6:b5:36:f2:48:d2:23:2a:8f:bb:a0:a4:                     ...                 Exponent: 65537 (0x10001)         Attributes:         Requested Extensions:             X509v3 Basic Constraints:                  CA:FALSE             X509v3 Subject Alternative Name:                  DNS:*.oats.org, DNS:*.oats.net, DNS:*.oats.in, DNS:oats.org, DNS:oats.net, DNS:oats.in             X509v3 Subject Key Identifier:                  C6:0E:59:B3:1A:FF:1A:A2:FF:F3:DC:76:21:F0:92:FC:57:88:05:6D     Signature Algorithm: sha1WithRSAEncryption          0d:45:6c:21:65:20:72:68:30:91:5f:fa:b8:c3:62:a0:66:a2:          96:6f:76:4a:ba:ca:e3:1d:9e:eb:47:d4:93:87:88:83:a2:f5:          ...

    Now we can see that there is a Request Extensions section with our coveted Subject Alternative Name field.

    A CA can still remove these fields or override them when issuing your certificate. Including them in your CSR does not guarantee that they will be in the final certificate.

    CA Key and self-signed Certificate

    Now let's play the CA part.

    Generate a key for the subject. It is the same as we did for our subject.

    $ openssl genrsa -out ca.key 2048 Generating RSA private key, 2048 bit long modulus ......................................................+++ .......+++ e is 65537 (0x10001)

    Generate a self signed certificate for the CA:

    $ openssl req -new -x509 -key ca.key -out ca.crt 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) [AU]:PT State or Province Name (full name) [Some-State]:Lisboa Locality Name (eg, city) []:Lisboa Organization Name (eg, company) [Internet Widgits Pty Ltd]:Sz CA Organizational Unit Name (eg, section) []:SZ CA Common Name (e.g. server FQDN or YOUR name) []: Email Address []:An optional company name []:

    OpenSSL uses the information you specify to compile a X.509 certificate using the information prompted to the user, the public key that is extracted from the specified private key which is also used to generate the signature.

    If we wish to include extensions in the self-signed certificate we could use a configuration file just like we did for the CSR but we would use x509_extensions instead of req_extensions.

    Signing

    One very easy way to sign a certificate is this:

    $ openssl x509 -req -in example.org.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out example.org.crt Signature ok subject=/C=PT/ST=Lisboa/L=Lisboa/O=Example Org/CN=*.example.org Getting CA Private Key

    Each issued certificate must contain a unique serial number assigned by the CA. It must be unique for each certificate given by a given CA. OpenSSL keeps the used serial numbers on a file, by default it has the same name as the CA certificate file with the extension replace by srl. So a file namedca.srl is created:

    $ cat ca.srl ED4B4A80662B1B4C

    This command produces the file example.org.crt which we can examine:

    $ openssl x509 -in example.org.crt -noout -text Certificate:     Data:         Version: 1 (0x0)         Serial Number: 17098842325572590412 (0xed4b4a80662b1b4c)     Signature Algorithm: sha1WithRSAEncryption         Issuer: C=PT, ST=Lisboa, L=Lisboa, O=Sz CA, OU=SZ CA         Validity             Not Before: Mar 20 22:46:43 2014 GMT             Not After : Apr 19 22:46:43 2014 GMT         Subject: C=PT, ST=Lisboa, L=Lisboa, O=Example Org, CN=*.example.org         Subject Public Key Info:             Public Key Algorithm: rsaEncryption                 Public-Key: (2048 bit)                 Modulus:                     00:ad:d8:71:1f:ab:a7:df:a6:c3:7e:d8:1f:fd:81:                     b0:5a:a8:9d:51:2b:15:c2:98:95:9e:fe:3b:7c:bd:                 Exponent: 65537 (0x10001)     Signature Algorithm: sha1WithRSAEncryption          05:21:5c:0f:4c:3c:9a:76:7f:3f:fb:fa:e0:09:03:05:c5:16:          bf:4b:ac:60:d8:86:fc:b2:42:3e:5e:19:45:2a:e2:01:83:67:

    Notice the serial number, in hex is exactly the contents of the created ca.srl file.

    I then setup an https server using the certificate and the key on port 1443 using bud. Bud is a TLS terminator, i.e. it unwraps https incoming connections and proxies them into a backend server as simple http. I forwarded bud connections into a static http server with a very simple index.html.

    I also added the line 127.0.0.1 www.example.org to my /etc/hosts to make my machine resolve the domain into the loopback address.

    I then pointed my browser to https://www.example.org:1443/. The browser immediately complained that certificate was invalid because it did not include the signing chain. What this means is the certificate says that the entity C=PT, ST=Lisboa, L=Lisboa, O=Example Org, CN=*.example.org is certified by the entity C=PT, ST=Lisboa, L=Lisboa, O=Sz CA, OU=SZ CA but there is no information as to who certifies this second entity, and since the entity is not known by the browser the certificate is deemed invalid.

    One thing we can do is create another file that contains the example.org certificate and the ca certificate.

    $ cat example.org.crt ca.crt > example.org.bundle.crt

    I did this and then my browser, Firefox, still rejected the certificate, but now with a different message. Now it complained that the SZ CA was not a trusted entity.

    So I opened my browser settings, and added the ca certificate to the Authorities section in the certificate store. And now it works!

    How to setup your own CA with OpenSSL

    Well... The browser doesn't give any warning. But it doesn't show the green icon you're probably already used to seing

    How to setup your own CA with OpenSSL

    This is because of extended validation, an extension we did not include in the certificate that usually requires the CA to verify the legal identification of the subject. Just to check it, we can ask the browser to export the certificate into a file we can query with openssl:

    $ openssl x509 -in github.com.crt -noout -text Certificate:     Data:         Version: 3 (0x2)         Serial Number:             04:7f:be:2e:4b:de:00:84:d2:ca:f8:e3:ec:fe:70:58     Signature Algorithm: sha1WithRSAEncryption         Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV CA-1         Validity             Not Before: Jun 10 00:00:00 2013 GMT             Not After : Sep  2 12:00:00 2015 GMT         Subject: businessCategory=Private Organization/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/serialNumber=5157550/street=548 4th Street/postalCode=94107, C=US, ST=California, L=San Francisco, O=GitHub, Inc., CN=github.com         Subject Public Key Info:             Public Key Algorithm: rsaEncryption                 Public-Key: (2048 bit)                 Modulus:                     00:ed:d3:89:c3:5d:70:72:09:f3:33:4f:1a:72:74:                     d9:b6:5a:95:50:bb:68:61:9f:f7:fb:1f:19:e1:da:                     ...                 Exponent: 65537 (0x10001)         X509v3 extensions:             X509v3 Authority Key Identifier:                  keyid:4C:58:CB:25:F0:41:4F:52:F4:28:C8:81:43:9B:A6:A8:A0:E6:92:E5             X509v3 Subject Key Identifier:                  87:D1:8F:19:6E:E4:87:6F:53:8C:77:91:07:50:DF:A3:BF:55:47:20             X509v3 Subject Alternative Name:                  DNS:github.com, DNS:www.github.com             X509v3 Key Usage: critical                 Digital Signature, Key Encipherment             X509v3 Extended Key Usage:                  TLS Web Server Authentication, TLS Web Client Authentication             X509v3 CRL Distribution Points:                  Full Name:                   URI:http://crl3.digicert.com/evca1-g2.crl                 Full Name:                   URI:http://crl4.digicert.com/evca1-g2.crl             X509v3 Certificate Policies:                  Policy: 2.16.840.1.114412.2.1                   CPS: http://www.digicert.com/ssl-cps-repository.htm                   User Notice:                     Explicit Text:              Authority Information Access:                  OCSP - URI:http://ocsp.digicert.com                 CA Issuers - URI:http://cacerts.digicert.com/DigiCertHighAssuranceEVCA-1.crt             X509v3 Basic Constraints: critical                 CA:FALSE     Signature Algorithm: sha1WithRSAEncryption          5f:15:6d:67:c3:3a:d5:a3:de:16:9c:45:33:26:d5:3d:c9:16:          74:34:ca:87:48:1b:14:90:6d:f5:ab:47:86:b9:f5:b8:e3:01:          ...

    The relevant extension for Extended Validation (EV) is Certificate Policies.

    Certificate sellers will refuse to issue wildcard certificates with EV, because cabforum.org, the regulatory body governing the issuance of EV SSL Certificates decided this is a big no no. EV certificates can, however, have as much SubjectAltName as you wish.

    openssl ca

    You can also sign CSRs with the ca(1).

    First we need a configuration file ca.conf:

    # we use 'ca' as the default section because we're usign the ca command # we use 'ca' as the default section because we're usign the ca command [ ca ] default_ca = my_ca [ my_ca ] #  a text file containing the next serial number to use in hex. Mandatory. #  This file must be present and contain a valid serial number. serial = ./serial # the text database file to use. Mandatory. This file must be present though # initially it will be empty. database = ./index.txt # specifies the directory where new certificates will be placed. Mandatory. new_certs_dir = ./newcerts # the file containing the CA certificate. Mandatory certificate = ./ca.crt # the file contaning the CA private key. Mandatory private_key = ./ca.key # the message digest algorithm. Remember to not use MD5 default_md = sha1 # for how many days will the signed certificate be valid default_days = 365 # a section with a set of variables corresponding to DN fields policy = my_policy [ my_policy ] # if the value is "match" then the field value must match the same field in the # CA certificate. If the value is "supplied" then it must be present. # Optional means it may be present. Any fields not mentioned are silently # deleted. countryName = match stateOrProvinceName = supplied organizationName = supplied commonName = supplied organizationalUnitName = optional commonName = supplied [ ca ] default_ca = my_ca [ my_ca ] #  a text file containing the next serial number to use in hex. Mandatory. #  This file must be present and contain a valid serial number. serial = ./serial # the text database file to use. Mandatory. This file must be present though # initially it will be empty. database = ./index.txt # specifies the directory where new certificates will be placed. Mandatory. new_certs_dir = ./newcerts # the file containing the CA certificate. Mandatory certificate = ./ca.crt # the file contaning the CA private key. Mandatory private_key = ./ca.key # the message digest algorithm. Remember to not use MD5 default_md = sha1 # for how many days will the signed certificate be valid default_days = 365 # a section with a set of variables corresponding to DN fields policy = my_policy [ my_policy ] # if the value is "match" then the field value must match the same field in the # CA certificate. If the value is "supplied" then it must be present. # Optional means it may be present. Any fields not mentioned are silently # deleted. countryName = match stateOrProvinceName = supplied organizationName = supplied commonName = supplied organizationalUnitName = optional commonName = supplied

    Remember, you can use man ca not only to see details about flags and command usage but also about the respective configuration sections and settings.

    We need to setup some structure first. The configuration file expects a newcerts directory, and theindex.txt and serial files:

    $ mkdir newcerts $ touch index.txt $ echo '01' > serial

    And now we can finally sign the certificate:

    $ openssl ca -config ca.cnf -out example.org.crt -infiles example.org.csr Using configuration from ca.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName           :PRINTABLE:'PT' stateOrProvinceName   :ASN.1 12:'Lisboa' localityName          :ASN.1 12:'Lisboa' organizationName      :ASN.1 12:'Example Org' commonName            :ASN.1 12:'*.example.org' Certificate is to be certified until Mar 21 01:13:36 2015 GMT (365 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

    If we wish to add extensions, or even to keep the extensions sent in a CSR (openssl will remove them when signing), then we need to also include that configuration.

    This is an extra configuration file oats.extensions.cnf:

    basicConstraints=CA:FALSE subjectAltName=@my_subject_alt_names subjectKeyIdentifier = hash [ my_subject_alt_names ] DNS.1 = *.oats.org DNS.2 = *.oats.net DNS.3 = *.oats.in DNS.4 = oats.org DNS.5 = oats.net DNS.6 = oats.in

    And now:

    $ openssl ca -config ca.cnf -out oats.crt -extfile oats.extensions.cnf -in oats.csr Using configuration from ca.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName           :PRINTABLE:'PT' stateOrProvinceName   :PRINTABLE:'Lisboa' localityName          :PRINTABLE:'Lisboa' organizationName      :PRINTABLE:'Oats In The Water' commonName            :T61STRING:'*.oats.org' Certificate is to be certified until Mar 21 01:43:11 2015 GMT (365 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

    We have a certificate that includes the SubjectAltNames we wanted:

    $ openssl x509 -in oats.crt -noout -text Certificate:     Data:         Version: 3 (0x2)         Serial Number: 2 (0x2)     Signature Algorithm: sha1WithRSAEncryption         Issuer: C=PT, ST=Lisboa, L=Lisboa, O=Sz CA, OU=SZ CA         Validity             Not Before: Mar 21 01:43:11 2014 GMT             Not After : Mar 21 01:43:11 2015 GMT         Subject: C=PT, ST=Lisboa, O=Oats In The Water, CN=*.oats.org         Subject Public Key Info:             Public Key Algorithm: rsaEncryption                 Public-Key: (2048 bit)                 Modulus:                     00:a2:58:fc:57:32:4d:40:aa:62:92:65:86:1d:6b:                     4f:3e:11:a6:b5:36:f2:48:d2:23:2a:8f:bb:a0:a4:                     ...                 Exponent: 65537 (0x10001)         X509v3 extensions:             X509v3 Basic Constraints:                  CA:FALSE             X509v3 Subject Alternative Name:                  DNS:*.oats.org, DNS:*.oats.net, DNS:*.oats.in, DNS:oats.org, DNS:oats.net, DNS:oats.in             X509v3 Subject Key Identifier:                  C6:0E:59:B3:1A:FF:1A:A2:FF:F3:DC:76:21:F0:92:FC:57:88:05:6D     Signature Algorithm: sha1WithRSAEncryption          89:7e:7d:67:1e:98:85:78:a1:f2:81:4c:b4:8c:f9:80:cd:47:          a9:94:94:a3:f0:dd:36:d3:e3:48:93:77:4a:31:16:03:79:9c:          ...

    We can verify the certificate is correct:

    $ openssl verify -CAfile ca.crt oats.crt oats.crt: OK

    That is all

    I know there a whole lot of stuff I didn't cover, important things like CRL. I'm sorry for that. This whole deal looks really messy and I hope we can ditch it for something better in the future.


    你可能感兴趣的:(How to setup your own CA with OpenSSL)