19

We have lots of embedded TLS clients on the field. TLS Servers must be authenticated.

Because long power cuts may reset clock of those devices, we have requirement to use certificates with validity period: from 19700101000001Z to 99991231235959Z.

How to use openssl to create certificate requests with those kind of validity period?

I only find the -days option for setting period, and that is not enough.

1
  • I developed a simple tool gossl that allows specifying cert validity start date and duration in various time units. It is an alternative to openssl, coded in Go, without dependencies, MIT license. Commented Nov 26, 2015 at 23:08

2 Answers 2

15

The "99991231235959Z" end of validity period may run you into trouble, because some software still converts date to an internal representation as a number of seconds since the "Epoch" (January 1st, 1970, 00:00 UTC) over a signed 32-bit integer. This internal representation fails on January 2038. Setting a validity period which spans beyond that fateful date may imply that your certificates will be rejected by some implementations.

Also, when a device sees its clock reset due to a long power cut, I suppose it does not get reset to a random date; it gets reset to a "default" date. Your certificate validity does not have to cover eight thousand years, but "just" the current days (for devices with a clock well adjusted) and the days around the default value to which clocks are reset when they lose power. Setting the validity period to range from 1970 to, say, 2037, ought to cover all cases, and will keep the internal representation (if used by a specific implementation) in the range where 32-bit signed arithmetic is good.

Be aware that if your devices do not have an accurate clock, then you will not have reliable revocation support, unless you enforce OCSP with client nonces.


That being said, validity period is not part of the certificate request. The period is chosen at the time the certificate is emitted, by the CA.

The OpenSSL command-line tool can be used as a very crude CA, although it was mostly designed for debugging. That tool offers "commands", two of which being able to create an X.509 certificate, x509 and req. Both provide only one option to adjust the validity period, which is the -days option. This is quite plainly visible if you take a look at the source code, e.g. in apps/x509.c:

            if ((x=X509_new()) == NULL) goto end;

            if (sno == NULL)
                    {
                    sno = ASN1_INTEGER_new();
                    if (!sno || !rand_serial(NULL, sno))
                            goto end;
                    if (!X509_set_serialNumber(x, sno))
                            goto end;
                    ASN1_INTEGER_free(sno);
                    sno = NULL;
                    }
            else if (!X509_set_serialNumber(x, sno))
                    goto end;

            if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
            if (!X509_set_subject_name(x,req->req_info->subject)) goto end;

            X509_gmtime_adj(X509_get_notBefore(x),0);
            X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL);

As you see in this code snippet, the new X.509 certificate structure is created, (and defaults the start and end of the validity period to the current date); the two last lines of the code adjust the validity period using the days parameter, and nothing else.

So if you want to adjust the validity period to arbitrary dates, you have two possibilities:

  • Set the current date of your computer to the start date you wish to use, so that openssl believes that we really are in the early 1970s; and set -days to 24000 or so. This is an awful hack and setting the clock of your computer back in the pre-Disco past might be difficult (modern computers automatically set their clock with NTP), and may break things (e.g. a MacOS X 10.5 computer will not be able to connect to WiFi if its clock is before year 2000).

  • Emit the certificate programmatically, using OpenSSL as a library, not as a command-line tool (alternative: modify OpenSSL source code to include the command-line options you need for x509 and/or req).

1
  • 4
    For the fake time approach, could you achieve the same result with libfaketime that's available through apt-get in Ubuntu. LD_PRELOAD=/usr/local/lib/libfaketime.so.1 FAKETIME="-15d" your_openssl_command
    – Jaakko
    Commented Feb 20, 2017 at 13:21
11

As Thomas Pornin said, the certificate request does not contain any dates, the notBefore and notAfter dates are set when the new certificate is created (signed) by the CA.

If you use the openssl ca tool, you can set them using -startdate date and -enddate date command line options or using default_startdate and default_enddate in [ca] section of the config file.

4
  • What's the format for date? Can you use the flag with a real value?
    – 425nesp
    Commented May 24, 2021 at 17:29
  • 1
    @425nesp it's output of date -u +%y%m%d%H%M%SZ for OpenSSL 0.9.x and date -u +%Y%m%d%H%M%SZ for newer versions (both 1.x and 3.0.x). Commented May 27, 2021 at 17:43
  • 1
    @HubertKario: actually for 1.0.0 up it's anything accepted by ASN1_TIME_set_string[_X509] which is either the %y or %Y format; for 1.0.0 through 1.1.0 %y encodes as 'utctime' and %Y as 'generalizedtime' which per rfc5280 should only be used outside the range 1950-2049, while for 1.1.1 and 3.0 it checks if %Y is within that range and if so internally reduces it to %y 'utctime'. Commented Aug 8, 2022 at 0:14
  • I was talking about output of date specifically, not how OpenSSL parses it, and generally you should use 4 digit year if at all possible, and that's what %Y with date will do. Commented Aug 17, 2022 at 12:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .