August 18, 2023

Since 2020, maximum lifetime of HTTPS certificates is limited to 1 year, exactly 398 days. I've previously written about the history and the reasons behind the change. But the reduced lifetime applies only to certificates issued from a public certification authority (CA) added to the operating system's or the browser's trusted root store by the vendor.

But the maximum lifetime of 1 year doesn't apply to certificates issued from or by a private root certification authority added by the user or the administrator of the computer either manually or with a tool like certutil or mkcert. That's also what Apple states on a page announcing the lifetime reduction to 398 days: This change will not affect certificates issued from user-added or administrator-added Root CAs.

User-added certification authority in macOS Keychain Access

But if you open Safari and try to load a page using a certificate issued by such private CA and valid for e.g. 5 years, the browser will refuse to load the page. The only thing you'll see is the following error message:

Safari cannot open the page because it could not establish a secure connection to the server.

That's it. There's no 🔓 This Connection Is Not Private, no details, no “continue to the site anyway, I (don't) know what I'm doing”, unlike in case of an expired or self-signed certificate.

Safari rules

This implies that Safari has some maximum lifetime rules or limits even for certificates issued by private authorities. But my Google-fu has failed to return anything useful so I had to do what was right: after finding a key for my private CA (called “exploited CA”), getting openssl, a web server, a Mac, and a calculator I've decided to empirically figure it out. I've quickly realized that a certificate with a lifetime of 398 days worked as well as a certificate valid for 800 days (2×398 + 4 days), but a certificate with a lifetime of 1592 days (4×398) did not.

16 certificates later, using half-interval search to find the right number between 800 and 1592, I arrived at a certificate with a validity of 825 days. That number seemed somewhat suspicious to me, and maybe that's why it occurred to me at that exact moment that the previous limit might still apply for private CAs. The previous max lifetime was, guess… 825 days. Of course Apple mentions it in their docs:

All TLS server certificates must comply with these new security requirements in iOS 13 and macOS 10.15 […] TLS server certificates must have a validity period of 825 days or fewer (as expressed in the NotBefore and NotAfter fields of the certificate).

That “all TLS certificates” is the important bit but of course I couldn't find this page before. And even if I did, I probably wouldn't get the connection anyway.

A certificate valid for 825 days worked of course, while a certificate valid for 826 days did not.

A certificate valid for 825 days, issued from my user-added CA, as shown in Safari's certi­ficate viewer

(No) limits in Chrome and Firefox

Both Chrome and Firefox will load a page with a private CA-issued certificate valid for 10 years, there seem to be no reduced lifetimes for user-added certification authorities in these browsers.

Chrome showing a certificate valid for 10 years (3650 days), don't mind the Common Name field 😅

A certificate valid for 10 years (3650 days) in Firefox certificate viewer

But if you'd like your e.g. developer environment usable in Safari, your internal certification authority should issue certificates valid for 825 days max, that's 2 years, 3 months and a few days. And of course, like with the latest lifetime reduction, it's Apple's “fault” 😊

And this is also why I dare to say that the validity of certificates issued from a user-added authorities is essentially limited to 2 years, even though this is really the case in just one browser. With the current validity limit of 398 days for certificates from public CAs, it is recommended to issue certificates with a maximum validity of 397 days, probably in case something miscalculates the seconds during daylight-saving shifts or so. In this case I'd also recommend setting a maximum of 824 days.

It's best to simplify or even automate it so that you can easily issue certificates valid for a maximum of one year or even less.

Michal Špaček

Michal Špaček

I build web applications and I'm into web application security. I like to speak about secure development. My mission is to teach web developers how to build secure and fast web applications and why.

Public trainings

Come to my public trainings, everybody's welcome: