Expose `not_before` and `not_after` for each Certificate
woodruffw opened this issue · comments
These are easy enough to extract with X509_get0_notBefore
and X509_get0_notAfter
.
Each returns an ASN1_TIME *
, which can be dumped to a BIO using ASN1_TIME_print
.
Hi, regarding that. I have tinkered a bit with it already.
It seems straightforward to go from ASN1_TIME
to tm
with ASN1_TIME_to_tm(X509_get0_notBefore(cert)
(e.g. in the Certificate
ctor). According to the documentation the converted time in tm
is GMT (= UTC). Perfect.
Now what I am wondering is how you envision such an exposure of these points of data.
Exposing tm
directly via const reference would be doable, of course. But I find tm
always a bit unwieldy with its semantics of year-1900 ... and months and days start at 0 and so on. However, it would still be easier for a developer to go from tm
to something else, so perhaps that's an argument in favor of exposing it anyway.
Would it be acceptable to introduce a struct which contains year, month, day (of month), hour, minute and second? E.g.
typedef struct
{
unsigned int year;
unsigned int month;
unsigned int day;
unsigned int hour;
unsigned int minute;
unsigned int second;
} cert_timestamp;
And is std::optional
the right way to go for when this value doesn't exist? I know, formally it should always exist, but what to do if the OpenSSL call failed or if we have something signed with some awkward self-signed certificate?
I agree re: tm
being unwieldy.
A custom struct seems reasonable, but before we commit to that completely: is there something in std::chrono
we can reuse? chrono::time_point
seems like it's roughly appropriate, although I'm not sure if there's a convenient way to construct it in our case.
Either way: I think we should raise an exception in the constructor if these time fields don't exist. AFAICT x.509 requires them, so we should as well.