Browsers have a list of trusted "certification authority" (CA) certificates. If a server's certificate is signed by one of those CA certificates and properly formed, you won't get the SSL warning.
Many browsers ship with many common CA certificates such as Verisign, Thawte, etc. Most browsers allow you to import a new CA into this list of trusted CAs.
Like creating your own self-signed server certificate, you can create your own self-signed CA certificate. You can then use that to sign your server certificate. If your CA is not provided by a well-known company, which it wouldn't be if it's one you made, it will have to be explicitly imported on the server side.
I've used xca
to do this before. It has templates for CAs and HTTP servers. The procedure is this:
- Create a private key for your CA
- Create a self-signed CA using this key using the "CA" template
- Create a private key for your proxy server
- Create a "certificate signing request" (CSR) using the second key, referencing the CA you just made.
- "Sign" the CSR and you'll have the proxy server certificate, which references your own CA.
You will then need to export (as a file if using xca
) the CA certificate (but don't include private key of course). A .pem
will be generated but you can change the extension to .crt
. When a user clicks on that, it will be offered to be installed on Firefox and Internet Explorer, and possibly other major browsers. As far as automatic installation of this .crt, you can:
- use group policy on IE
- direct users to an introduction page asking them to download/install the .crt if they want to avoid warnings.
You can then use the export functions on HTTP server certificate (export both private key and certificate for the server side) to put on your proxy server.
You have two ways of creating certificates in the past. Either faking the time (1)(2), or defining the time interval when signing the certificate (3).
1) Firstly, about faking the time: to make one program think it is in a different date from the system, have a look at libfaketime
and faketime
To install it in Debian:
sudo apt-get install faketime
You would then use faketime
before the openssl
command.
For examples of use:
$faketime 'last friday 5 pm' /bin/date
Fri Apr 14 17:00:00 WEST 2017
$faketime '2008-12-24 08:15:42' /bin/date
Wed Dec 24 08:15:42 WET 2008
From man faketime
:
The given command will be tricked into believing that the
current
system time is the one specified in the timestamp. The wall clock will
continue to run from this date and time unless specified otherwise (see
advanced options). Actually, faketime is a simple wrapper for
libfaketime, which uses the LD_PRELOAD mechanism to load a small
library which intercepts system calls to functions such as time(2) and
fstat(2).
So for instance, in your case, you can very well define a date of 2008, and create then a certificate with the validity of 2 years up to 2010.
faketime '2008-12-24 08:15:42' openssl ...
As a side note, this utility can be used in several Unix versions, including MacOS, as an wrapper to any kind of programs (not exclusive to the command line).
As a clarification, only the binaries loaded with this method (and their children) have their time changed, and the fake time does not affect the current time of the rest of the system.
2) As @Wyzard states, you also have the datefudge
package which is very similar in use to faketime
.
As differences, datefudge
does not influence fstat
(i.e. does not change file time creation). It also has it´s own library, datefudge.so, that it loads using LD_PRELOAD.
It also has a -s
static time
where the time referenced is always returned despite how many extra seconds have passed.
$ datefudge --static "2007-04-01 10:23" sh -c "sleep 3; date -R"
Sun, 01 Apr 2007 10:23:00 +0100
3) Besides faking the time, and even more simply, you can also define the starting point and ending point of validity of the certificate when signing the certificate in OpenSSL.
The misconception of the question you link to in your question, is that certificate validity is not defined at request time (at the CSR request), but when signing it.
When using openssl ca
to create the self-signed certificate, add the options -startdate
and -enddate
.
The date format in those two options, according to openssl sources at openssl/crypto/x509/x509_vfy.c
, is ASN1_TIME aka ASN1UTCTime: the format must be either YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ.
Quoting openssl/crypto/x509/x509_vfy.c
:
int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
{
static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1;
static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1;
ASN1_TIME *asn1_cmp_time = NULL;
int i, day, sec, ret = 0;
/*
* Note that ASN.1 allows much more slack in the time format than RFC5280.
* In RFC5280, the representation is fixed:
* UTCTime: YYMMDDHHMMSSZ
* GeneralizedTime: YYYYMMDDHHMMSSZ
*
* We do NOT currently enforce the following RFC 5280 requirement:
* "CAs conforming to this profile MUST always encode certificate
* validity dates through the year 2049 as UTCTime; certificate validity
* dates in 2050 or later MUST be encoded as GeneralizedTime."
*/
And from the CHANGE log (2038 bug?) - This change log is just as an additional footnote, as it only concerns those using directly the API.
Changes between 1.1.0e and 1.1.1 [xx XXX xxxx]
*) Add the ASN.1 types INT32, UINT32, INT64, UINT64 and variants prefixed
with Z. These are meant to replace LONG and ZLONG and to be size safe.
The use of LONG and ZLONG is discouraged and scheduled for deprecation
in OpenSSL 1.2.0.
So, creating a certificate from the 1st of January 2008 to the 1st of January of 2010, can be done as:
openssl ca -config /path/to/myca.conf -in req.csr -out ourdomain.pem \
-startdate 200801010000Z -enddate 201001010000Z
or
openssl ca -config /path/to/myca.conf -in req.csr -out ourdomain.pem \
-startdate 0801010000Z -enddate 1001010000Z
-startdate
and -enddate
do appear in the openssl
sources and CHANGE log; as @guntbert noted, while they do not appear in the main man openssl
page, they also appear in man ca
:
-startdate date
this allows the start date to be explicitly set. The format of the date is
YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure).
-enddate date
this allows the expiry date to be explicitly set. The format of the date is
YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure).
Quoting openssl/CHANGE
:
Changes between 0.9.3a and 0.9.4 [09 Aug 1999]
*) Fix -startdate and -enddate (which was missing) arguments to 'ca'
program.
P.S. As for the chosen answer of the question you reference from StackExchange: it is generally a bad idea to change the system time, especially in production systems; and with the methods in this answer you do not need root privileges when using them.
Best Answer
You can't use this command to generate a well formed X.509 certificate. It will be malformed because the hostname is placed in the Common Name (CN). Placing a hostname or IP Address in the CN is deprecated by both the IETF (most tools, like
wget
andcurl
) and CA/B Forums (CA's and Browsers).According to both the IETF and CA/B Forums, Server names and IP Addresses always go in the Subject Alternate Name (SAN). For the rules, see RFC 5280, Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile and CA/Browser Forum Baseline Requirements.
You mostly need to use an OpenSSL configuration file and tailor it to suit your needs. Below is an example of one I use. It's called
example-com.conf
, and it's passed to the OpenSSL command via-config example-com.conf
.Also note well: all machines claim to be
localhost
,localhost.localdomain
, etc. Be careful about issuing certificates forlocalhost
. I'm not saying don't do it; just understand there are some risks involved.Alternatives to
localhost
are: (1) run DNS and issue certificates to the machine's DNS name. Or, (2) use static IP and include the static IP address.The Browsers will still give you warnings about a self signed certificate that does not chain back to a trusted root. Tools like
curl
andwget
will not complain, but you still need to trust you self signed with an option like cURL's--cafile
. To overcome the Browser trust issue, you have to become your own CA."Becoming your own CA" is known as running a Private PKI. There's not much to it. You can do everything a Public CA can do. The only thing different is you will need to install your Root CA Certificate in the various stores. It's no different than, say, using cURL's
cacerts.pm
.cacerts.pm
is just a collection of Root CA's, and now you have joined the club.If you become your own CA, then be sure to burn your Root CA private key to disc and keep it offline. Then pop it in your CD/DVD drive when you need to sign a signing request. Now you are issuing certificates just like a Public CA.
None of this is terribly difficult once you sign one or two signing requests. I've been running a Private PKI for years at the house. All my devices and gadgets trust my CA.
For more information on becoming your own CA, see How do you sign Certificate Signing Request with your Certification Authority and How to create a self-signed certificate with openssl?.
From the comments in the configuration file below...
Self Signed (note the addition of -x509)
Signing Request (note the lack of -x509)
Print a Self Signed
Print a Signing Request
Configuration File
You may need to do the following for Chrome. Otherwise Chrome may complain a Common Name is invalid (
ERR_CERT_COMMON_NAME_INVALID
). I'm not sure what the relationship is between an IP address in the SAN and a CN in this instance.