[Python-checkins] gh-104773: PEP 594: Remove the crypt module (#104908)

vstinner webhook-mailer at python.org
Thu May 25 09:45:54 EDT 2023


https://github.com/python/cpython/commit/e4127eaa1ea9104be0a1d9d9e147d50ba88f59aa
commit: e4127eaa1ea9104be0a1d9d9e147d50ba88f59aa
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2023-05-25T15:45:46+02:00
summary:

gh-104773: PEP 594: Remove the crypt module (#104908)

Remove the crypt module and its private _crypt extension, deprecated
in Python 3.11.

files:
A Misc/NEWS.d/next/Library/2023-05-25-00-53-08.gh-issue-104773.Iyjtt0.rst
D Doc/library/crypt.rst
D Lib/crypt.py
D Lib/test/test_crypt.py
D Modules/_cryptmodule.c
D Modules/clinic/_cryptmodule.c.h
M Doc/library/crypto.rst
M Doc/library/pwd.rst
M Doc/library/superseded.rst
M Doc/license.rst
M Doc/whatsnew/3.11.rst
M Doc/whatsnew/3.12.rst
M Doc/whatsnew/3.13.rst
M Doc/whatsnew/3.3.rst
M Doc/whatsnew/3.6.rst
M Doc/whatsnew/3.7.rst
M Doc/whatsnew/3.9.rst
M Lib/test/test___all__.py
M Misc/NEWS.d/3.12.0a1.rst
M Misc/NEWS.d/3.9.0a1.rst
M Modules/Setup
M Modules/Setup.stdlib.in
M Python/stdlib_module_names.h
M Tools/wasm/Setup.local.example
M Tools/wasm/wasm_assets.py
M configure
M configure.ac
M pyconfig.h.in

diff --git a/Doc/library/crypt.rst b/Doc/library/crypt.rst
deleted file mode 100644
index 740084b40c5ac..0000000000000
--- a/Doc/library/crypt.rst
+++ /dev/null
@@ -1,182 +0,0 @@
-:mod:`crypt` --- Function to check Unix passwords
-=================================================
-
-.. module:: crypt
-   :platform: Unix
-   :synopsis: The crypt() function used to check Unix passwords.
-   :deprecated:
-
-.. moduleauthor:: Steven D. Majewski <sdm7g at virginia.edu>
-.. sectionauthor:: Steven D. Majewski <sdm7g at virginia.edu>
-.. sectionauthor:: Peter Funk <pf at artcom-gmbh.de>
-
-**Source code:** :source:`Lib/crypt.py`
-
-.. index::
-   single: crypt(3)
-   pair: cipher; DES
-
-.. deprecated-removed:: 3.11 3.13
-   The :mod:`crypt` module is deprecated
-   (see :pep:`PEP 594 <594#crypt>` for details and alternatives).
-   The :mod:`hashlib` module is a potential replacement for certain use cases.
-
---------------
-
-This module implements an interface to the :manpage:`crypt(3)` routine, which is
-a one-way hash function based upon a modified DES algorithm; see the Unix man
-page for further details.  Possible uses include storing hashed passwords
-so you can check passwords without storing the actual password, or attempting
-to crack Unix passwords with a dictionary.
-
-.. index:: single: crypt(3)
-
-Notice that the behavior of this module depends on the actual implementation  of
-the :manpage:`crypt(3)` routine in the running system.  Therefore, any
-extensions available on the current implementation will also  be available on
-this module.
-
-.. availability:: Unix, not VxWorks.
-
-.. include:: ../includes/wasm-notavail.rst
-
-Hashing Methods
----------------
-
-.. versionadded:: 3.3
-
-The :mod:`crypt` module defines the list of hashing methods (not all methods
-are available on all platforms):
-
-.. data:: METHOD_SHA512
-
-   A Modular Crypt Format method with 16 character salt and 86 character
-   hash based on the SHA-512 hash function.  This is the strongest method.
-
-.. data:: METHOD_SHA256
-
-   Another Modular Crypt Format method with 16 character salt and 43
-   character hash based on the SHA-256 hash function.
-
-.. data:: METHOD_BLOWFISH
-
-   Another Modular Crypt Format method with 22 character salt and 31
-   character hash based on the Blowfish cipher.
-
-   .. versionadded:: 3.7
-
-.. data:: METHOD_MD5
-
-   Another Modular Crypt Format method with 8 character salt and 22
-   character hash based on the MD5 hash function.
-
-.. data:: METHOD_CRYPT
-
-   The traditional method with a 2 character salt and 13 characters of
-   hash.  This is the weakest method.
-
-
-Module Attributes
------------------
-
-.. versionadded:: 3.3
-
-.. attribute:: methods
-
-   A list of available password hashing algorithms, as
-   ``crypt.METHOD_*`` objects.  This list is sorted from strongest to
-   weakest.
-
-
-Module Functions
-----------------
-
-The :mod:`crypt` module defines the following functions:
-
-.. function:: crypt(word, salt=None)
-
-   *word* will usually be a user's password as typed at a prompt or  in a graphical
-   interface.  The optional *salt* is either a string as returned from
-   :func:`mksalt`, one of the ``crypt.METHOD_*`` values (though not all
-   may be available on all platforms), or a full encrypted password
-   including salt, as returned by this function.  If *salt* is not
-   provided, the strongest method available in :attr:`methods` will be used.
-
-   Checking a password is usually done by passing the plain-text password
-   as *word* and the full results of a previous :func:`crypt` call,
-   which should be the same as the results of this call.
-
-   *salt* (either a random 2 or 16 character string, possibly prefixed with
-   ``$digit$`` to indicate the method) which will be used to perturb the
-   encryption algorithm.  The characters in *salt* must be in the set
-   ``[./a-zA-Z0-9]``, with the exception of Modular Crypt Format which
-   prefixes a ``$digit$``.
-
-   Returns the hashed password as a string, which will be composed of
-   characters from the same alphabet as the salt.
-
-   .. index:: single: crypt(3)
-
-   Since a few :manpage:`crypt(3)` extensions allow different values, with
-   different sizes in the *salt*, it is recommended to use  the full crypted
-   password as salt when checking for a password.
-
-   .. versionchanged:: 3.3
-      Accept ``crypt.METHOD_*`` values in addition to strings for *salt*.
-
-
-.. function:: mksalt(method=None, *, rounds=None)
-
-   Return a randomly generated salt of the specified method.  If no
-   *method* is given, the strongest method available in :attr:`methods` is
-   used.
-
-   The return value is a string suitable for passing as the *salt* argument
-   to :func:`crypt`.
-
-   *rounds* specifies the number of rounds for ``METHOD_SHA256``,
-   ``METHOD_SHA512`` and ``METHOD_BLOWFISH``.
-   For ``METHOD_SHA256`` and ``METHOD_SHA512`` it must be an integer between
-   ``1000`` and ``999_999_999``, the default is ``5000``.  For
-   ``METHOD_BLOWFISH`` it must be a power of two between ``16`` (2\ :sup:`4`)
-   and ``2_147_483_648`` (2\ :sup:`31`), the default is ``4096``
-   (2\ :sup:`12`).
-
-   .. versionadded:: 3.3
-
-   .. versionchanged:: 3.7
-      Added the *rounds* parameter.
-
-
-Examples
---------
-
-A simple example illustrating typical use (a constant-time comparison
-operation is needed to limit exposure to timing attacks.
-:func:`hmac.compare_digest` is suitable for this purpose)::
-
-   import pwd
-   import crypt
-   import getpass
-   from hmac import compare_digest as compare_hash
-
-   def login():
-       username = input('Python login: ')
-       cryptedpasswd = pwd.getpwnam(username)[1]
-       if cryptedpasswd:
-           if cryptedpasswd == 'x' or cryptedpasswd == '*':
-               raise ValueError('no support for shadow passwords')
-           cleartext = getpass.getpass()
-           return compare_hash(crypt.crypt(cleartext, cryptedpasswd), cryptedpasswd)
-       else:
-           return True
-
-To generate a hash of a password using the strongest available method and
-check it against the original::
-
-   import crypt
-   from hmac import compare_digest as compare_hash
-
-   hashed = crypt.crypt(plaintext)
-   if not compare_hash(hashed, crypt.crypt(plaintext, hashed)):
-       raise ValueError("hashed version doesn't validate against original")
diff --git a/Doc/library/crypto.rst b/Doc/library/crypto.rst
index ae45549a6d894..5a3b7a807213f 100644
--- a/Doc/library/crypto.rst
+++ b/Doc/library/crypto.rst
@@ -8,7 +8,6 @@ Cryptographic Services
 
 The modules described in this chapter implement various algorithms of a
 cryptographic nature.  They are available at the discretion of the installation.
-On Unix systems, the :mod:`crypt` module may also be available.
 Here's an overview:
 
 
diff --git a/Doc/library/pwd.rst b/Doc/library/pwd.rst
index 25aa8b82754de..300419301b9ff 100644
--- a/Doc/library/pwd.rst
+++ b/Doc/library/pwd.rst
@@ -39,10 +39,8 @@ raised if the entry asked for cannot be found.
 
 .. note::
 
-   .. index:: pair: module; crypt
-
    In traditional Unix the field ``pw_passwd`` usually contains a password
-   encrypted with a DES derived algorithm (see module :mod:`crypt`).  However most
+   encrypted with a DES derived algorithm.  However most
    modern unices  use a so-called *shadow password* system.  On those unices the
    *pw_passwd* field only contains an asterisk (``'*'``) or the  letter ``'x'``
    where the encrypted password is stored in a file :file:`/etc/shadow` which is
diff --git a/Doc/library/superseded.rst b/Doc/library/superseded.rst
index 1e7b3787f06e0..284716e8845de 100644
--- a/Doc/library/superseded.rst
+++ b/Doc/library/superseded.rst
@@ -13,7 +13,6 @@ backwards compatibility. They have been superseded by other modules.
    aifc.rst
    audioop.rst
    chunk.rst
-   crypt.rst
    imghdr.rst
    optparse.rst
    uu.rst
diff --git a/Doc/license.rst b/Doc/license.rst
index 005d048b6eb20..947a9b1a8c5ac 100644
--- a/Doc/license.rst
+++ b/Doc/license.rst
@@ -655,7 +655,7 @@ copyright and licensing notice::
 OpenSSL
 -------
 
-The modules :mod:`hashlib`, :mod:`posix`, :mod:`ssl`, :mod:`crypt` use
+The modules :mod:`hashlib`, :mod:`posix` and :mod:`ssl` use
 the OpenSSL library for added performance if made available by the
 operating system. Additionally, the Windows and macOS installers for
 Python may include a copy of the OpenSSL libraries, so we include a copy
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 2382500960caa..efff13211c798 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -1733,7 +1733,7 @@ Modules
   +---------------------+---------------------+---------------------+---------------------+---------------------+
   | :mod:`aifc`         | :mod:`chunk`        | :mod:`!msilib`      | :mod:`!pipes`       | :mod:`!telnetlib`   |
   +---------------------+---------------------+---------------------+---------------------+---------------------+
-  | :mod:`audioop`      | :mod:`crypt`        | :mod:`!nis`         | :mod:`!sndhdr`      | :mod:`uu`           |
+  | :mod:`audioop`      | :mod:`!crypt`       | :mod:`!nis`         | :mod:`!sndhdr`      | :mod:`uu`           |
   +---------------------+---------------------+---------------------+---------------------+---------------------+
   | :mod:`!cgi`         | :mod:`imghdr`       | :mod:`!nntplib`     | :mod:`!spwd`        | :mod:`!xdrlib`      |
   +---------------------+---------------------+---------------------+---------------------+---------------------+
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index 0e4ccab14bafc..f01cc27f70622 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -923,7 +923,7 @@ Modules (see :pep:`594`):
 * :mod:`!cgi`
 * :mod:`!cgitb`
 * :mod:`chunk`
-* :mod:`crypt`
+* :mod:`!crypt`
 * :mod:`imghdr`
 * :mod:`!mailcap`
 * :mod:`!msilib`
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index bfd0995752b24..f570e0354daf6 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -201,6 +201,22 @@ Removed
 * :pep:`594`: Remove the :mod:`!msilib` module, deprecated in Python 3.11.
   (Contributed by Zachary Ware in :gh:`104773`.)
 
+* :pep:`594`: Remove the :mod:`!crypt` module and its private :mod:`!_crypt`
+  extension, deprecated in Python 3.11.
+  The :mod:`hashlib` module is a potential replacement for certain use cases.
+  Otherwise, the following PyPI projects can be used:
+
+  * `bcrypt <https://pypi.org/project/bcrypt/>`_:
+    Modern password hashing for your software and your servers.
+  * `passlib <https://pypi.org/project/passlib/>`_:
+    Comprehensive password hashing framework supporting over 30 schemes.
+  * `argon2-cffi <https://pypi.org/project/argon2-cffi/>`_:
+    The secure Argon2 password hashing algorithm.
+  * `legacycrypt <https://pypi.org/project/legacycrypt/>`_:
+    Wrapper to the POSIX crypt library call and associated functionality.
+
+  (Contributed by Victor Stinner in :gh:`104773`.)
+
 
 Porting to Python 3.13
 ======================
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index b25cf3673d1c4..3dca7227a91c3 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -1052,8 +1052,8 @@ their ``__init__`` method (for example, file objects) or in their
 crypt
 -----
 
-Addition of salt and modular crypt format (hashing method) and the :func:`~crypt.mksalt`
-function to the :mod:`crypt` module.
+Addition of salt and modular crypt format (hashing method) and the :func:`~!crypt.mksalt`
+function to the :mod:`!crypt` module.
 
 (:issue:`10924`)
 
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index 944da78e9184b..b45dc80820c9d 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -2274,7 +2274,7 @@ Changes in the Python API
   :class:`~collections.OrderedDict`.
   (Contributed by Steve Holden in :issue:`27842`.)
 
-* The :const:`crypt.METHOD_CRYPT` will no longer be added to ``crypt.methods``
+* The :const:`!crypt.METHOD_CRYPT` will no longer be added to ``crypt.methods``
   if unsupported by the platform.
   (Contributed by Victor Stinner in :issue:`25287`.)
 
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index 8b4aa17c21402..93915b2030e17 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -848,10 +848,10 @@ alternative to script path.  (Contributed by Sanyam Khurana in :issue:`21862`.)
 crypt
 -----
 
-The :mod:`crypt` module now supports the Blowfish hashing method.
+The :mod:`!crypt` module now supports the Blowfish hashing method.
 (Contributed by Serhiy Storchaka in :issue:`31664`.)
 
-The :func:`~crypt.mksalt` function now allows specifying the number of rounds
+The :func:`~!crypt.mksalt` function now allows specifying the number of rounds
 for hashing.  (Contributed by Serhiy Storchaka in :issue:`31702`.)
 
 
diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst
index a1a4bf32b9b32..6656779e1a1ba 100644
--- a/Doc/whatsnew/3.9.rst
+++ b/Doc/whatsnew/3.9.rst
@@ -83,7 +83,7 @@ Interpreter improvements:
   now sped up using :pep:`590` vectorcall;
 * garbage collection does not block on resurrected objects;
 * a number of Python modules (:mod:`_abc`, :mod:`audioop`, :mod:`_bz2`,
-  :mod:`_codecs`, :mod:`_contextvars`, :mod:`_crypt`, :mod:`_functools`,
+  :mod:`_codecs`, :mod:`_contextvars`, :mod:`!_crypt`, :mod:`_functools`,
   :mod:`_json`, :mod:`_locale`, :mod:`math`, :mod:`operator`, :mod:`resource`,
   :mod:`time`, :mod:`_weakref`) now use multiphase initialization as defined
   by PEP 489;
diff --git a/Lib/crypt.py b/Lib/crypt.py
deleted file mode 100644
index de4a14a388476..0000000000000
--- a/Lib/crypt.py
+++ /dev/null
@@ -1,124 +0,0 @@
-"""Wrapper to the POSIX crypt library call and associated functionality."""
-
-import sys as _sys
-
-try:
-    import _crypt
-except ModuleNotFoundError:
-    if _sys.platform == 'win32':
-        raise ImportError("The crypt module is not supported on Windows")
-    else:
-        raise ImportError("The required _crypt module was not built as part of CPython")
-
-import errno
-import string as _string
-import warnings
-from random import SystemRandom as _SystemRandom
-from collections import namedtuple as _namedtuple
-
-
-warnings._deprecated(__name__, remove=(3, 13))
-
-
-_saltchars = _string.ascii_letters + _string.digits + './'
-_sr = _SystemRandom()
-
-
-class _Method(_namedtuple('_Method', 'name ident salt_chars total_size')):
-
-    """Class representing a salt method per the Modular Crypt Format or the
-    legacy 2-character crypt method."""
-
-    def __repr__(self):
-        return '<crypt.METHOD_{}>'.format(self.name)
-
-
-def mksalt(method=None, *, rounds=None):
-    """Generate a salt for the specified method.
-
-    If not specified, the strongest available method will be used.
-
-    """
-    if method is None:
-        method = methods[0]
-    if rounds is not None and not isinstance(rounds, int):
-        raise TypeError(f'{rounds.__class__.__name__} object cannot be '
-                        f'interpreted as an integer')
-    if not method.ident:  # traditional
-        s = ''
-    else:  # modular
-        s = f'${method.ident}$'
-
-    if method.ident and method.ident[0] == '2':  # Blowfish variants
-        if rounds is None:
-            log_rounds = 12
-        else:
-            log_rounds = int.bit_length(rounds-1)
-            if rounds != 1 << log_rounds:
-                raise ValueError('rounds must be a power of 2')
-            if not 4 <= log_rounds <= 31:
-                raise ValueError('rounds out of the range 2**4 to 2**31')
-        s += f'{log_rounds:02d}$'
-    elif method.ident in ('5', '6'):  # SHA-2
-        if rounds is not None:
-            if not 1000 <= rounds <= 999_999_999:
-                raise ValueError('rounds out of the range 1000 to 999_999_999')
-            s += f'rounds={rounds}$'
-    elif rounds is not None:
-        raise ValueError(f"{method} doesn't support the rounds argument")
-
-    s += ''.join(_sr.choice(_saltchars) for char in range(method.salt_chars))
-    return s
-
-
-def crypt(word, salt=None):
-    """Return a string representing the one-way hash of a password, with a salt
-    prepended.
-
-    If ``salt`` is not specified or is ``None``, the strongest
-    available method will be selected and a salt generated.  Otherwise,
-    ``salt`` may be one of the ``crypt.METHOD_*`` values, or a string as
-    returned by ``crypt.mksalt()``.
-
-    """
-    if salt is None or isinstance(salt, _Method):
-        salt = mksalt(salt)
-    return _crypt.crypt(word, salt)
-
-
-#  available salting/crypto methods
-methods = []
-
-def _add_method(name, *args, rounds=None):
-    method = _Method(name, *args)
-    globals()['METHOD_' + name] = method
-    salt = mksalt(method, rounds=rounds)
-    result = None
-    try:
-        result = crypt('', salt)
-    except OSError as e:
-        # Not all libc libraries support all encryption methods.
-        if e.errno in {errno.EINVAL, errno.EPERM, errno.ENOSYS}:
-            return False
-        raise
-    if result and len(result) == method.total_size:
-        methods.append(method)
-        return True
-    return False
-
-_add_method('SHA512', '6', 16, 106)
-_add_method('SHA256', '5', 16, 63)
-
-# Choose the strongest supported version of Blowfish hashing.
-# Early versions have flaws.  Version 'a' fixes flaws of
-# the initial implementation, 'b' fixes flaws of 'a'.
-# 'y' is the same as 'b', for compatibility
-# with openwall crypt_blowfish.
-for _v in 'b', 'y', 'a', '':
-    if _add_method('BLOWFISH', '2' + _v, 22, 59 + len(_v), rounds=1<<4):
-        break
-
-_add_method('MD5', '1', 8, 34)
-_add_method('CRYPT', None, 2, 13)
-
-del _v, _add_method
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index ecf73b3ad1beb..6b0e2b020d0bc 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -13,9 +13,9 @@
 
 if support.check_sanitizer(address=True, memory=True):
     # bpo-46633: test___all__ is skipped because importing some modules
-    # directly can trigger known problems with ASAN (like tk or crypt).
+    # directly can trigger known problems with ASAN (like tk).
     raise unittest.SkipTest("workaround ASAN build issues on loading tests "
-                            "like tk or crypt")
+                            "like tk")
 
 
 class NoAll(RuntimeError):
diff --git a/Lib/test/test_crypt.py b/Lib/test/test_crypt.py
deleted file mode 100644
index b2a5ce6db0919..0000000000000
--- a/Lib/test/test_crypt.py
+++ /dev/null
@@ -1,112 +0,0 @@
-import sys
-import unittest
-from test.support import check_sanitizer, warnings_helper
-
-
-try:
-    if check_sanitizer(address=True, memory=True):
-        raise unittest.SkipTest("The crypt module SEGFAULTs on ASAN/MSAN builds")
-    crypt = warnings_helper.import_deprecated("crypt")
-    IMPORT_ERROR = None
-except ImportError as ex:
-    if sys.platform != 'win32':
-        raise unittest.SkipTest(str(ex))
-    crypt = None
-    IMPORT_ERROR = str(ex)
-
-
- at unittest.skipUnless(sys.platform == 'win32', 'This should only run on windows')
- at unittest.skipIf(crypt, 'import succeeded')
-class TestWhyCryptDidNotImport(unittest.TestCase):
-
-    def test_import_failure_message(self):
-        self.assertIn('not supported', IMPORT_ERROR)
-
-
- at unittest.skipUnless(crypt, 'crypt module is required')
-class CryptTestCase(unittest.TestCase):
-
-    def test_crypt(self):
-        cr = crypt.crypt('mypassword')
-        cr2 = crypt.crypt('mypassword', cr)
-        self.assertEqual(cr2, cr)
-        cr = crypt.crypt('mypassword', 'ab')
-        if cr is not None:
-            cr2 = crypt.crypt('mypassword', cr)
-            self.assertEqual(cr2, cr)
-
-    def test_salt(self):
-        self.assertEqual(len(crypt._saltchars), 64)
-        for method in crypt.methods:
-            salt = crypt.mksalt(method)
-            self.assertIn(len(salt) - method.salt_chars, {0, 1, 3, 4, 6, 7})
-            if method.ident:
-                self.assertIn(method.ident, salt[:len(salt)-method.salt_chars])
-
-    def test_saltedcrypt(self):
-        for method in crypt.methods:
-            cr = crypt.crypt('assword', method)
-            self.assertEqual(len(cr), method.total_size)
-            cr2 = crypt.crypt('assword', cr)
-            self.assertEqual(cr2, cr)
-            cr = crypt.crypt('assword', crypt.mksalt(method))
-            self.assertEqual(len(cr), method.total_size)
-
-    def test_methods(self):
-        self.assertTrue(len(crypt.methods) >= 1)
-        if sys.platform.startswith('openbsd'):
-            self.assertEqual(crypt.methods, [crypt.METHOD_BLOWFISH])
-        else:
-            self.assertEqual(crypt.methods[-1], crypt.METHOD_CRYPT)
-
-    @unittest.skipUnless(
-        crypt
-        and (
-            crypt.METHOD_SHA256 in crypt.methods or crypt.METHOD_SHA512 in crypt.methods
-        ),
-        'requires support of SHA-2',
-    )
-    def test_sha2_rounds(self):
-        for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512):
-            for rounds in 1000, 10_000, 100_000:
-                salt = crypt.mksalt(method, rounds=rounds)
-                self.assertIn('$rounds=%d$' % rounds, salt)
-                self.assertEqual(len(salt) - method.salt_chars,
-                                 11 + len(str(rounds)))
-                cr = crypt.crypt('mypassword', salt)
-                self.assertTrue(cr)
-                cr2 = crypt.crypt('mypassword', cr)
-                self.assertEqual(cr2, cr)
-
-    @unittest.skipUnless(
-        crypt and crypt.METHOD_BLOWFISH in crypt.methods, 'requires support of Blowfish'
-    )
-    def test_blowfish_rounds(self):
-        for log_rounds in range(4, 11):
-            salt = crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1 << log_rounds)
-            self.assertIn('$%02d$' % log_rounds, salt)
-            self.assertIn(len(salt) - crypt.METHOD_BLOWFISH.salt_chars, {6, 7})
-            cr = crypt.crypt('mypassword', salt)
-            self.assertTrue(cr)
-            cr2 = crypt.crypt('mypassword', cr)
-            self.assertEqual(cr2, cr)
-
-    def test_invalid_rounds(self):
-        for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512,
-                       crypt.METHOD_BLOWFISH):
-            with self.assertRaises(TypeError):
-                crypt.mksalt(method, rounds='4096')
-            with self.assertRaises(TypeError):
-                crypt.mksalt(method, rounds=4096.0)
-            for rounds in (0, 1, -1, 1<<999):
-                with self.assertRaises(ValueError):
-                    crypt.mksalt(method, rounds=rounds)
-        with self.assertRaises(ValueError):
-            crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1000)
-        for method in (crypt.METHOD_CRYPT, crypt.METHOD_MD5):
-            with self.assertRaisesRegex(ValueError, 'support'):
-                crypt.mksalt(method, rounds=4096)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/Misc/NEWS.d/3.12.0a1.rst b/Misc/NEWS.d/3.12.0a1.rst
index 2e1d39b0c7996..d706343adf583 100644
--- a/Misc/NEWS.d/3.12.0a1.rst
+++ b/Misc/NEWS.d/3.12.0a1.rst
@@ -2650,7 +2650,7 @@ calling any callbacks. Patch by Kumar Aditya.
 .. section: Library
 
 Fail gracefully if :data:`~errno.EPERM` or :data:`~errno.ENOSYS` is raised
-when loading :mod:`crypt` methods. This may happen when trying to load
+when loading :mod:`!crypt` methods. This may happen when trying to load
 ``MD5`` on a Linux kernel with :abbr:`FIPS (Federal Information Processing
 Standard)` enabled.
 
diff --git a/Misc/NEWS.d/3.9.0a1.rst b/Misc/NEWS.d/3.9.0a1.rst
index f75d42285cf11..5ae14293df3e3 100644
--- a/Misc/NEWS.d/3.9.0a1.rst
+++ b/Misc/NEWS.d/3.9.0a1.rst
@@ -4856,7 +4856,7 @@ Patch by Srinivas Nyayapati.
 .. nonce: Akreij
 .. section: Windows
 
-Trying to import the :mod:`crypt` module on Windows will result in an
+Trying to import the :mod:`!crypt` module on Windows will result in an
 :exc:`ImportError` with a message explaining that the module isn't supported
 on Windows. On other platforms, if the underlying ``_crypt`` module is not
 available, the ImportError will include a message explaining the problem.
diff --git a/Misc/NEWS.d/next/Library/2023-05-25-00-53-08.gh-issue-104773.Iyjtt0.rst b/Misc/NEWS.d/next/Library/2023-05-25-00-53-08.gh-issue-104773.Iyjtt0.rst
new file mode 100644
index 0000000000000..d5443aef80d48
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-05-25-00-53-08.gh-issue-104773.Iyjtt0.rst
@@ -0,0 +1,2 @@
+:pep:`594`: Remove the :mod:`!crypt` module and its private :mod:`!_crypt`
+extension, deprecated in Python 3.11. Patch by Victor Stinner.
diff --git a/Modules/Setup b/Modules/Setup
index 05d037bdca922..7953913694d83 100644
--- a/Modules/Setup
+++ b/Modules/Setup
@@ -188,10 +188,6 @@ PYTHONPATH=$(COREPYTHONPATH)
 #syslog syslogmodule.c
 #termios termios.c
 
-# Modules with UNIX dependencies that require external libraries
-
-#_crypt _cryptmodule.c -lcrypt
-
 # Modules that require external libraries.
 
 #_bz2 _bz2module.c -lbz2
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index ef3c5644fd0fd..e244efcad4995 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -106,8 +106,6 @@
 # Modules with some UNIX dependencies
 #
 
-# needs -lcrypt on some systems
- at MODULE__CRYPT_TRUE@_crypt _cryptmodule.c
 @MODULE_FCNTL_TRUE at fcntl fcntlmodule.c
 @MODULE_GRP_TRUE at grp grpmodule.c
 @MODULE_MMAP_TRUE at mmap mmapmodule.c
diff --git a/Modules/_cryptmodule.c b/Modules/_cryptmodule.c
deleted file mode 100644
index 75035084c9cd2..0000000000000
--- a/Modules/_cryptmodule.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* cryptmodule.c - by Steve Majewski
- */
-
-#include "Python.h"
-
-#include <sys/types.h>
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
-
-/* Module crypt */
-
-/*[clinic input]
-module crypt
-[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c6252cf4f2f2ae81]*/
-
-#include "clinic/_cryptmodule.c.h"
-
-/*[clinic input]
-crypt.crypt
-
-    word: str
-    salt: str
-    /
-
-Hash a *word* with the given *salt* and return the hashed password.
-
-*word* will usually be a user's password.  *salt* (either a random 2 or 16
-character string, possibly prefixed with $digit$ to indicate the method)
-will be used to perturb the encryption algorithm and produce distinct
-results for a given *word*.
-
-[clinic start generated code]*/
-
-static PyObject *
-crypt_crypt_impl(PyObject *module, const char *word, const char *salt)
-/*[clinic end generated code: output=0512284a03d2803c input=0e8edec9c364352b]*/
-{
-    char *crypt_result;
-#ifdef HAVE_CRYPT_R
-    struct crypt_data data;
-    memset(&data, 0, sizeof(data));
-    crypt_result = crypt_r(word, salt, &data);
-#else
-    crypt_result = crypt(word, salt);
-#endif
-    if (crypt_result == NULL) {
-        return PyErr_SetFromErrno(PyExc_OSError);
-    }
-    return Py_BuildValue("s", crypt_result);
-}
-
-
-static PyMethodDef crypt_methods[] = {
-    CRYPT_CRYPT_METHODDEF
-    {NULL,              NULL}           /* sentinel */
-};
-
-static PyModuleDef_Slot _crypt_slots[] = {
-    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
-    {0, NULL}
-};
-
-static struct PyModuleDef cryptmodule = {
-    PyModuleDef_HEAD_INIT,
-    "_crypt",
-    NULL,
-    0,
-    crypt_methods,
-    _crypt_slots,
-    NULL,
-    NULL,
-    NULL
-};
-
-PyMODINIT_FUNC
-PyInit__crypt(void)
-{
-    return PyModuleDef_Init(&cryptmodule);
-}
diff --git a/Modules/clinic/_cryptmodule.c.h b/Modules/clinic/_cryptmodule.c.h
deleted file mode 100644
index 97b70b3c17e9a..0000000000000
--- a/Modules/clinic/_cryptmodule.c.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*[clinic input]
-preserve
-[clinic start generated code]*/
-
-#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
-#  include "pycore_gc.h"            // PyGC_Head
-#  include "pycore_runtime.h"       // _Py_ID()
-#endif
-
-
-PyDoc_STRVAR(crypt_crypt__doc__,
-"crypt($module, word, salt, /)\n"
-"--\n"
-"\n"
-"Hash a *word* with the given *salt* and return the hashed password.\n"
-"\n"
-"*word* will usually be a user\'s password.  *salt* (either a random 2 or 16\n"
-"character string, possibly prefixed with $digit$ to indicate the method)\n"
-"will be used to perturb the encryption algorithm and produce distinct\n"
-"results for a given *word*.");
-
-#define CRYPT_CRYPT_METHODDEF    \
-    {"crypt", _PyCFunction_CAST(crypt_crypt), METH_FASTCALL, crypt_crypt__doc__},
-
-static PyObject *
-crypt_crypt_impl(PyObject *module, const char *word, const char *salt);
-
-static PyObject *
-crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
-{
-    PyObject *return_value = NULL;
-    const char *word;
-    const char *salt;
-
-    if (!_PyArg_CheckPositional("crypt", nargs, 2, 2)) {
-        goto exit;
-    }
-    if (!PyUnicode_Check(args[0])) {
-        _PyArg_BadArgument("crypt", "argument 1", "str", args[0]);
-        goto exit;
-    }
-    Py_ssize_t word_length;
-    word = PyUnicode_AsUTF8AndSize(args[0], &word_length);
-    if (word == NULL) {
-        goto exit;
-    }
-    if (strlen(word) != (size_t)word_length) {
-        PyErr_SetString(PyExc_ValueError, "embedded null character");
-        goto exit;
-    }
-    if (!PyUnicode_Check(args[1])) {
-        _PyArg_BadArgument("crypt", "argument 2", "str", args[1]);
-        goto exit;
-    }
-    Py_ssize_t salt_length;
-    salt = PyUnicode_AsUTF8AndSize(args[1], &salt_length);
-    if (salt == NULL) {
-        goto exit;
-    }
-    if (strlen(salt) != (size_t)salt_length) {
-        PyErr_SetString(PyExc_ValueError, "embedded null character");
-        goto exit;
-    }
-    return_value = crypt_crypt_impl(module, word, salt);
-
-exit:
-    return return_value;
-}
-/*[clinic end generated code: output=235ccef9211184f4 input=a9049054013a1b77]*/
diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h
index f2d3ecb975356..00742b39a327c 100644
--- a/Python/stdlib_module_names.h
+++ b/Python/stdlib_module_names.h
@@ -22,7 +22,6 @@ static const char* _Py_stdlib_module_names[] = {
 "_compat_pickle",
 "_compression",
 "_contextvars",
-"_crypt",
 "_csv",
 "_ctypes",
 "_curses",
@@ -121,7 +120,6 @@ static const char* _Py_stdlib_module_names[] = {
 "contextvars",
 "copy",
 "copyreg",
-"crypt",
 "csv",
 "ctypes",
 "curses",
diff --git a/Tools/wasm/Setup.local.example b/Tools/wasm/Setup.local.example
index ad58c31a2efe3..e3778c94ad0c8 100644
--- a/Tools/wasm/Setup.local.example
+++ b/Tools/wasm/Setup.local.example
@@ -3,7 +3,6 @@
 _asyncio
 audioop
 _bz2
-_crypt
 _decimal
 _pickle
 pyexpat _elementtree
diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py
index c3db5d203498d..5e59ee7ef3752 100755
--- a/Tools/wasm/wasm_assets.py
+++ b/Tools/wasm/wasm_assets.py
@@ -81,7 +81,6 @@
 OMIT_MODULE_FILES = {
     "_asyncio": ["asyncio/"],
     "audioop": ["aifc.py", "wave.py"],
-    "_crypt": ["crypt.py"],
     "_curses": ["curses/"],
     "_ctypes": ["ctypes/"],
     "_decimal": ["decimal.py"],
diff --git a/configure b/configure
index ab35842179d42..319b06d5e4c93 100755
--- a/configure
+++ b/configure
@@ -678,8 +678,6 @@ MODULE__CURSES_FALSE
 MODULE__CURSES_TRUE
 MODULE__CTYPES_FALSE
 MODULE__CTYPES_TRUE
-MODULE__CRYPT_FALSE
-MODULE__CRYPT_TRUE
 MODULE__BLAKE2_FALSE
 MODULE__BLAKE2_TRUE
 MODULE__SHA3_FALSE
@@ -818,8 +816,6 @@ HAVE_GETHOSTBYNAME_R
 HAVE_GETHOSTBYNAME_R_3_ARG
 HAVE_GETHOSTBYNAME_R_5_ARG
 HAVE_GETHOSTBYNAME_R_6_ARG
-LIBCRYPT_LIBS
-LIBCRYPT_CFLAGS
 LIBOBJS
 LIBLZMA_LIBS
 LIBLZMA_CFLAGS
@@ -1118,8 +1114,6 @@ BZIP2_CFLAGS
 BZIP2_LIBS
 LIBLZMA_CFLAGS
 LIBLZMA_LIBS
-LIBCRYPT_CFLAGS
-LIBCRYPT_LIBS
 LIBREADLINE_CFLAGS
 LIBREADLINE_LIBS
 LIBEDIT_CFLAGS
@@ -1940,10 +1934,6 @@ Some influential environment variables:
               C compiler flags for LIBLZMA, overriding pkg-config
   LIBLZMA_LIBS
               linker flags for LIBLZMA, overriding pkg-config
-  LIBCRYPT_CFLAGS
-              C compiler flags for LIBCRYPT, overriding pkg-config
-  LIBCRYPT_LIBS
-              linker flags for LIBCRYPT, overriding pkg-config
   LIBREADLINE_CFLAGS
               C compiler flags for LIBREADLINE, overriding pkg-config
   LIBREADLINE_LIBS
@@ -9618,7 +9608,7 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h
 
 # checks for header files
 for ac_header in  \
-  alloca.h asm/types.h bluetooth.h conio.h crypt.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \
+  alloca.h asm/types.h bluetooth.h conio.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \
   ieeefp.h io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/memfd.h \
   linux/random.h linux/soundcard.h \
   linux/tipc.h linux/wait.h netdb.h net/ethernet.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \
@@ -18767,297 +18757,6 @@ fi
 done
 
 
-
-
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBCRYPT" >&5
-$as_echo_n "checking for LIBCRYPT... " >&6; }
-
-if test -n "$LIBCRYPT_CFLAGS"; then
-    pkg_cv_LIBCRYPT_CFLAGS="$LIBCRYPT_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxcrypt >= 3.1.1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libxcrypt >= 3.1.1") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_LIBCRYPT_CFLAGS=`$PKG_CONFIG --cflags "libxcrypt >= 3.1.1" 2>/dev/null`
-		      test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$LIBCRYPT_LIBS"; then
-    pkg_cv_LIBCRYPT_LIBS="$LIBCRYPT_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxcrypt >= 3.1.1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libxcrypt >= 3.1.1") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_LIBCRYPT_LIBS=`$PKG_CONFIG --libs "libxcrypt >= 3.1.1" 2>/dev/null`
-		      test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-	        LIBCRYPT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxcrypt >= 3.1.1" 2>&1`
-        else
-	        LIBCRYPT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxcrypt >= 3.1.1" 2>&1`
-        fi
-	# Put the nasty error message in config.log where it belongs
-	echo "$LIBCRYPT_PKG_ERRORS" >&5
-
-
-  save_CFLAGS=$CFLAGS
-save_CPPFLAGS=$CPPFLAGS
-save_LDFLAGS=$LDFLAGS
-save_LIBS=$LIBS
-
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5
-$as_echo_n "checking for library containing crypt_r... " >&6; }
-if ${ac_cv_search_crypt_r+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char crypt_r ();
-int
-main ()
-{
-return crypt_r ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' crypt; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_crypt_r=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_crypt_r+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_crypt_r+:} false; then :
-
-else
-  ac_cv_search_crypt_r=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt_r" >&5
-$as_echo "$ac_cv_search_crypt_r" >&6; }
-ac_res=$ac_cv_search_crypt_r
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-      $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h
-
-      if test "$ac_cv_search_crypt_r" = "none required"; then
-        libcrypt=
-      else
-        libcrypt="$ac_cv_search_crypt_r"
-      fi
-      LIBCRYPT_LIBS=${LIBCRYPT_LIBS-$libcrypt}
-
-fi
-
-
-CFLAGS=$save_CFLAGS
-CPPFLAGS=$save_CPPFLAGS
-LDFLAGS=$save_LDFLAGS
-LIBS=$save_LIBS
-
-
-
-elif test $pkg_failed = untried; then
-     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-  save_CFLAGS=$CFLAGS
-save_CPPFLAGS=$CPPFLAGS
-save_LDFLAGS=$LDFLAGS
-save_LIBS=$LIBS
-
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5
-$as_echo_n "checking for library containing crypt_r... " >&6; }
-if ${ac_cv_search_crypt_r+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char crypt_r ();
-int
-main ()
-{
-return crypt_r ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' crypt; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_crypt_r=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_crypt_r+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_crypt_r+:} false; then :
-
-else
-  ac_cv_search_crypt_r=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt_r" >&5
-$as_echo "$ac_cv_search_crypt_r" >&6; }
-ac_res=$ac_cv_search_crypt_r
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-      $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h
-
-      if test "$ac_cv_search_crypt_r" = "none required"; then
-        libcrypt=
-      else
-        libcrypt="$ac_cv_search_crypt_r"
-      fi
-      LIBCRYPT_LIBS=${LIBCRYPT_LIBS-$libcrypt}
-
-fi
-
-
-CFLAGS=$save_CFLAGS
-CPPFLAGS=$save_CPPFLAGS
-LDFLAGS=$save_LDFLAGS
-LIBS=$save_LIBS
-
-
-
-else
-	LIBCRYPT_CFLAGS=$pkg_cv_LIBCRYPT_CFLAGS
-	LIBCRYPT_LIBS=$pkg_cv_LIBCRYPT_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-  $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h
-
-
-fi
-
-save_CFLAGS=$CFLAGS
-save_CPPFLAGS=$CPPFLAGS
-save_LDFLAGS=$LDFLAGS
-save_LIBS=$LIBS
-
-
-  CPPFLAGS="$CPPFLAGS $LIBCRYPT_CFLAGS"
-  LIBS="$LIBCRYPT_LIBS $LIBS"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt or crypt_r" >&5
-$as_echo_n "checking for crypt or crypt_r... " >&6; }
-if ${ac_cv_crypt_crypt+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-        #ifdef HAVE_CRYPT_H
-          #include <crypt.h>
-        #endif
-        #include <unistd.h>
-
-int
-main ()
-{
-
-        #ifdef HAVE_CRYPT_R
-          void *x = crypt_r;
-        #else
-          void *x = crypt;
-        #endif
-
-  ;
-  return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_crypt_crypt=yes
-else
-  ac_cv_crypt_crypt=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_crypt_crypt" >&5
-$as_echo "$ac_cv_crypt_crypt" >&6; }
-
-CFLAGS=$save_CFLAGS
-CPPFLAGS=$save_CPPFLAGS
-LDFLAGS=$save_LDFLAGS
-LIBS=$save_LIBS
-
-
-
 for ac_func in clock_gettime
 do :
   ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
@@ -25376,7 +25075,6 @@ case $ac_sys_system in #(
 
 
     py_cv_module__scproxy=n/a
-    py_cv_module__crypt=n/a
     py_cv_module_termios=n/a
     py_cv_module_grp=n/a
  ;; #(
@@ -26774,40 +26472,6 @@ $as_echo "$py_cv_module__blake2" >&6; }
 
 
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _crypt" >&5
-$as_echo_n "checking for stdlib extension module _crypt... " >&6; }
-        if test "$py_cv_module__crypt" != "n/a"; then :
-
-    if true; then :
-  if test "$ac_cv_crypt_crypt" = yes; then :
-  py_cv_module__crypt=yes
-else
-  py_cv_module__crypt=missing
-fi
-else
-  py_cv_module__crypt=disabled
-fi
-
-fi
-  as_fn_append MODULE_BLOCK "MODULE__CRYPT_STATE=$py_cv_module__crypt$as_nl"
-  if test "x$py_cv_module__crypt" = xyes; then :
-
-    as_fn_append MODULE_BLOCK "MODULE__CRYPT_CFLAGS=$LIBCRYPT_CFLAGS$as_nl"
-    as_fn_append MODULE_BLOCK "MODULE__CRYPT_LDFLAGS=$LIBCRYPT_LIBS$as_nl"
-
-fi
-   if test "$py_cv_module__crypt" = yes; then
-  MODULE__CRYPT_TRUE=
-  MODULE__CRYPT_FALSE='#'
-else
-  MODULE__CRYPT_TRUE='#'
-  MODULE__CRYPT_FALSE=
-fi
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__crypt" >&5
-$as_echo "$py_cv_module__crypt" >&6; }
-
-
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _ctypes" >&5
 $as_echo_n "checking for stdlib extension module _ctypes... " >&6; }
         if test "$py_cv_module__ctypes" != "n/a"; then :
@@ -28046,10 +27710,6 @@ if test -z "${MODULE__BLAKE2_TRUE}" && test -z "${MODULE__BLAKE2_FALSE}"; then
   as_fn_error $? "conditional \"MODULE__BLAKE2\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${MODULE__CRYPT_TRUE}" && test -z "${MODULE__CRYPT_FALSE}"; then
-  as_fn_error $? "conditional \"MODULE__CRYPT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
 if test -z "${MODULE__CTYPES_TRUE}" && test -z "${MODULE__CTYPES_FALSE}"; then
   as_fn_error $? "conditional \"MODULE__CTYPES\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/configure.ac b/configure.ac
index 09e5eff2c5332..587d1034514c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2810,7 +2810,7 @@ AC_DEFINE(STDC_HEADERS, 1, [Define to 1 if you have the ANSI C header files.])
 
 # checks for header files
 AC_CHECK_HEADERS([ \
-  alloca.h asm/types.h bluetooth.h conio.h crypt.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \
+  alloca.h asm/types.h bluetooth.h conio.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \
   ieeefp.h io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/memfd.h \
   linux/random.h linux/soundcard.h \
   linux/tipc.h linux/wait.h netdb.h net/ethernet.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \
@@ -5049,48 +5049,6 @@ AC_CHECK_FUNCS(setpgrp,
 # check for namespace functions
 AC_CHECK_FUNCS([setns unshare])
 
-dnl We search for both crypt and crypt_r as one or the other may be defined
-dnl libxcrypt provides <crypt.h> and libcrypt with crypt_r() since
-dnl at least 3.1.1 from 2015.
-dnl FreeBSD defines crypt_r() in <unistd.h>
-AH_TEMPLATE([HAVE_CRYPT_R], [Define if you have the crypt_r() function.])
-
-PKG_CHECK_MODULES([LIBCRYPT], [libxcrypt >= 3.1.1], [
-  AC_DEFINE([HAVE_CRYPT_R], [1])
-], [
-  WITH_SAVE_ENV([
-    AC_SEARCH_LIBS([crypt_r], [crypt], [
-      AC_DEFINE([HAVE_CRYPT_R], [1])
-      if test "$ac_cv_search_crypt_r" = "none required"; then
-        libcrypt=
-      else
-        libcrypt="$ac_cv_search_crypt_r"
-      fi
-      LIBCRYPT_LIBS=${LIBCRYPT_LIBS-$libcrypt}
-    ])
-  ])
-])
-
-WITH_SAVE_ENV([
-  CPPFLAGS="$CPPFLAGS $LIBCRYPT_CFLAGS"
-  LIBS="$LIBCRYPT_LIBS $LIBS"
-  AC_CACHE_CHECK([for crypt or crypt_r], [ac_cv_crypt_crypt], [
-    AC_LINK_IFELSE([AC_LANG_PROGRAM([
-        #ifdef HAVE_CRYPT_H
-          #include <crypt.h>
-        #endif
-        #include <unistd.h>
-      ], [
-        #ifdef HAVE_CRYPT_R
-          void *x = crypt_r;
-        #else
-          void *x = crypt;
-        #endif
-      ])
-    ], [ac_cv_crypt_crypt=yes], [ac_cv_crypt_crypt=no])
-  ])
-])
-
 AC_CHECK_FUNCS(clock_gettime, [], [
     AC_CHECK_LIB(rt, clock_gettime, [
         LIBS="$LIBS -lrt"
@@ -7060,10 +7018,9 @@ AC_DEFUN([PY_STDLIB_MOD_SET_NA], [
 
 # stdlib not available
 dnl Modules that are not available on some platforms
-dnl VxWorks does not provide crypt() function
 AS_CASE([$ac_sys_system],
   [AIX], [PY_STDLIB_MOD_SET_NA([_scproxy])],
-  [VxWorks*], [PY_STDLIB_MOD_SET_NA([_scproxy], [_crypt], [termios], [grp])],
+  [VxWorks*], [PY_STDLIB_MOD_SET_NA([_scproxy], [termios], [grp])],
   dnl The _scproxy module is available on macOS
   [Darwin], [],
   [CYGWIN*], [PY_STDLIB_MOD_SET_NA([_scproxy])],
@@ -7271,9 +7228,6 @@ PY_STDLIB_MOD([_blake2],
   [test "$with_builtin_blake2" = yes], [],
   [$LIBB2_CFLAGS], [$LIBB2_LIBS])
 
-PY_STDLIB_MOD([_crypt],
-  [], [test "$ac_cv_crypt_crypt" = yes],
-  [$LIBCRYPT_CFLAGS], [$LIBCRYPT_LIBS])
 PY_STDLIB_MOD([_ctypes],
   [], [test "$have_libffi" = yes],
   [$NO_STRICT_OVERFLOW_CFLAGS $LIBFFI_CFLAGS], [$LIBFFI_LIBS])
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 46b3448b40409..694fea93cf7a5 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -175,12 +175,6 @@
 /* Define to 1 if you have the `copy_file_range' function. */
 #undef HAVE_COPY_FILE_RANGE
 
-/* Define to 1 if you have the <crypt.h> header file. */
-#undef HAVE_CRYPT_H
-
-/* Define if you have the crypt_r() function. */
-#undef HAVE_CRYPT_R
-
 /* Define to 1 if you have the `ctermid' function. */
 #undef HAVE_CTERMID
 



More information about the Python-checkins mailing list