Skip to content

Commit 0abf9ec

Browse files
authored
add utcnow() helper function to avoid datetime.utcnow() (#1229)
Using datetime.utcnow() triggers a deprecation warning in Python 3.12. This leads to test failures in projects using PyOpenSSL (e.g. josepy). I considered two possible approaches to solve this issue: - compare tz-aware datetime instances (basically use `datetime.strptime(time_string, "%Y%m%d%H%M%S%z")`) - strip `tzinfo` from a tz-aware "utcnow" (`datetime.now(timezone.utc).replace(tzinfo=None)`. In the end I went with the second option because `self.get_notAfter()` returns the "ASN.1 TIME" format which I think is supposed to always have a "Z" at the end. If we use `%z` as a format string for `.strptime()` we would accept also other formats.
1 parent 0fe822d commit 0abf9ec

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

src/OpenSSL/crypto.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1437,7 +1437,9 @@ def has_expired(self) -> bool:
14371437
time_string = time_bytes.decode("utf-8")
14381438
not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
14391439

1440-
return not_after < datetime.datetime.utcnow()
1440+
UTC = datetime.timezone.utc
1441+
utcnow = datetime.datetime.now(UTC).replace(tzinfo=None)
1442+
return not_after < utcnow
14411443

14421444
def _get_boundary_time(self, which: Any) -> Optional[bytes]:
14431445
return _get_asn1_time(which(self._x509))

tests/test_crypto.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import base64
88
import sys
99
import warnings
10-
from datetime import datetime, timedelta
10+
from datetime import datetime, timedelta, timezone
1111
from subprocess import PIPE, Popen
1212

1313
from cryptography import x509
@@ -68,6 +68,10 @@ def normalize_privatekey_pem(pem):
6868
return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
6969

7070

71+
def utcnow():
72+
return datetime.now(timezone.utc).replace(tzinfo=None)
73+
74+
7175
GOOD_CIPHER = "blowfish"
7276
BAD_CIPHER = "zippers"
7377

@@ -1865,14 +1869,14 @@ def test_gmtime_adj_notBefore(self):
18651869
current time plus the number of seconds passed in.
18661870
"""
18671871
cert = load_certificate(FILETYPE_PEM, self.pemData)
1868-
not_before_min = datetime.utcnow().replace(microsecond=0) + timedelta(
1872+
not_before_min = utcnow().replace(microsecond=0) + timedelta(
18691873
seconds=100
18701874
)
18711875
cert.gmtime_adj_notBefore(100)
18721876
not_before = datetime.strptime(
18731877
cert.get_notBefore().decode(), "%Y%m%d%H%M%SZ"
18741878
)
1875-
not_before_max = datetime.utcnow() + timedelta(seconds=100)
1879+
not_before_max = utcnow() + timedelta(seconds=100)
18761880
assert not_before_min <= not_before <= not_before_max
18771881

18781882
def test_gmtime_adj_notAfter_wrong_args(self):
@@ -1891,14 +1895,14 @@ def test_gmtime_adj_notAfter(self):
18911895
to be the current time plus the number of seconds passed in.
18921896
"""
18931897
cert = load_certificate(FILETYPE_PEM, self.pemData)
1894-
not_after_min = datetime.utcnow().replace(microsecond=0) + timedelta(
1898+
not_after_min = utcnow().replace(microsecond=0) + timedelta(
18951899
seconds=100
18961900
)
18971901
cert.gmtime_adj_notAfter(100)
18981902
not_after = datetime.strptime(
18991903
cert.get_notAfter().decode(), "%Y%m%d%H%M%SZ"
19001904
)
1901-
not_after_max = datetime.utcnow() + timedelta(seconds=100)
1905+
not_after_max = utcnow() + timedelta(seconds=100)
19021906
assert not_after_min <= not_after <= not_after_max
19031907

19041908
def test_has_expired(self):

0 commit comments

Comments
 (0)