From 29f31c6a7645e2828e542d9b1c590d284e9c6c49 Mon Sep 17 00:00:00 2001 From: Andrew Moon Date: Wed, 18 Sep 2024 09:56:24 +0900 Subject: [PATCH] crypto: add Date fields for `validTo` and `validFrom` Added equivalent fields to `X509Certificate` in Date form. PR-URL: https://github.com/nodejs/node/pull/54159 Reviewed-By: James M Snell Reviewed-By: Tim Perry Reviewed-By: Anna Henningsen Reviewed-By: Richard Lau Reviewed-By: Daeyeon Jeong --- deps/ncrypto/ncrypto.cc | 41 ++++++++++++++++ deps/ncrypto/ncrypto.h | 2 + doc/api/crypto.md | 20 ++++++++ lib/internal/crypto/x509.js | 20 ++++++++ src/crypto/crypto_x509.cc | 37 +++++++++++++++ test/parallel/test-crypto-x509.js | 77 +++++++++++++++++++++++++++++++ 6 files changed, 197 insertions(+) diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index eb3533bb4623b1..5a9bdcd8c68d89 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -356,6 +356,35 @@ int PasswordCallback(char* buf, int size, int rwflag, void* u) { return -1; } +// Algorithm: http://howardhinnant.github.io/date_algorithms.html +constexpr int days_from_epoch(int y, unsigned m, unsigned d) +{ + y -= m <= 2; + const int era = (y >= 0 ? y : y - 399) / 400; + const unsigned yoe = static_cast(y - era * 400); // [0, 399] + const unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365] + const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096] + return era * 146097 + static_cast(doe) - 719468; +} + +// tm must be in UTC +// using time_t causes problems on 32-bit systems and windows x64. +int64_t PortableTimeGM(struct tm* t) { + int year = t->tm_year + 1900; + int month = t->tm_mon; + if (month > 11) { + year += month / 12; + month %= 12; + } else if (month < 0) { + int years_diff = (11 - month) / 12; + year -= years_diff; + month += 12 * years_diff; + } + int days_since_epoch = days_from_epoch(year, month + 1, t->tm_mday); + + return 60 * (60 * (24LL * static_cast(days_since_epoch) + t->tm_hour) + t->tm_min) + t->tm_sec; +} + // ============================================================================ // SPKAC @@ -826,6 +855,18 @@ BIOPointer X509View::getValidTo() const { return bio; } +int64_t X509View::getValidToTime() const { + struct tm tp; + ASN1_TIME_to_tm(X509_get0_notAfter(cert_), &tp); + return PortableTimeGM(&tp); +} + +int64_t X509View::getValidFromTime() const { + struct tm tp; + ASN1_TIME_to_tm(X509_get0_notBefore(cert_), &tp); + return PortableTimeGM(&tp); +} + DataPointer X509View::getSerialNumber() const { ClearErrorOnReturn clearErrorOnReturn; if (cert_ == nullptr) return {}; diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index 60bfce3ea8999e..f8c4d35ade3174 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -462,6 +462,8 @@ class X509View final { BIOPointer getInfoAccess() const; BIOPointer getValidFrom() const; BIOPointer getValidTo() const; + int64_t getValidFromTime() const; + int64_t getValidToTime() const; DataPointer getSerialNumber() const; Result getPublicKey() const; StackOfASN1 getKeyUsage() const; diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 435d5d495609b3..7cccbaffc20cb8 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -2865,6 +2865,16 @@ added: v15.6.0 The date/time from which this certificate is valid. +### `x509.validFromDate` + + + +* Type: {Date} + +The date/time from which this certificate is valid, encapsulated in a `Date` object. + ### `x509.validTo` + +* Type: {Date} + +The date/time until which this certificate is valid, encapsulated in a `Date` object. + ### `x509.verify(publicKey)`