Python3 is removing crypt.crypt and not replacing it with anything
eighty-twenty.org
eighty-twenty.org
In the PEP (https://peps.python.org/pep-0594/#crypt) it points out that this module didn't work on Windows at all and didn't provide any useful real-world functionality on Linux, BSD or macOS.
The use case mentioned in this blog (SHA512 password hashing) is considered a bad practice because unlike bcrypt, SHA512 is fast for an attacker to execute to check if a credential guess matches a hash.
They just came over from the Java string interpolation thread, because after not reading the JEP they weren‘t sure how to spend the rest of the evening and thought „I know! Now I will not read the PEP.“ /s
Linux distros are converging towards using libxcrypt with yescrypt, which is a modern password hashing function. If you have a crypt function that wires back to libxcrypt's crypt, you can use that.
It's a bit unfortunate that people seem to be unable to agree on a modern password hash (other places tend to use scrypt or argon2), but well, I think yescrypt is fine, and having a way to generate and verify crypt-compatible hashes is certainly useful functionality.
Highlight:
> Only DES encryption is guaranteed to be available. DES has an extremely limited key space of 2*56.
A good solution would:
* Puke warnings on the screen when using insecure algorithms
* Guarantee secure algorithms everywhere
These algorithms aren't hard to implement, and anything relying on DES will be faster in interpreted Python than in optimized code on the 80486 it was intended to run on.
I'd rather have this removed than broken, but it makes sense to just fix it.
As a footnote, a lot of code doesn't rely on this for anything high-stakes. If this is hashing passwords on my local machine, it's a backup to a backup for security. It should move to something modern, but it breaking in the meantime is a bigger failure than an obsolete crypto algorithm.
As I understand it, they are difficult to implement securely. By that I mean avoid side channel (often timing) attacks.
There's also a lot of precedent for removing these security footguns from the stdlib that no one actually uses. From the top of my head, the `imgop` library and the `cgi.escape` function. (My personal bugbear is `csv.Sniffer` which, as far as I can see, has no correct use case, it's just broken.)
I'm somewhat out of touch with Python, but as far as I know, it's been best practice to use `cryptography`[1] for a long, long time.
ETA: Just to note - DES is super, super broken. It shouldn't even be an option. DES was published in 1975. 3DES was published in 1981 - DES has been considered too small a keyspace since 1981. That's older than Python. Exporting DES in your crypto API is a bug. (Apparently, according to Wikipedia, NIST has deprecated all use of DES [including legacy applications] as of 2023. But they only deprecated new applications in 2017, so perhaps I overstate.)
https://manpages.debian.org/unstable/libcrypt-dev/crypt.5.en...
So, if you're on an ancient unix box (or a Mac, apparently), then you're stuck with the obsolete standard library your OS vendor packaged, but that's true of other things.
Presumably, they'll remove SSL support soon too, since, when provided with a sufficiently old version of openssl support, it won't provide modern algorithms either. That means "only obsolete SSL modes are guaranteed to be available".
This package says it's a drop-in replacement for the library. https://pypi.org/project/py-purecrypt/
> We did not want to hurt the people using Python 2. So, in 2008, we announced that we would sunset Python 2 in 2015, and asked people to upgrade before then. Some did, but many did not. So, in 2014, we extended that sunset till 2020.
https://www.python.org/doc/sunset-python-2/
It blows my mind some people are still on Python 2, but I worked at a place that shifted an app to Python 3 in 2021, so I guess I'm one to talk. (Incidentally, I have written much more Python 3 than I ever wrote Python 2, but I still write print without parenthesis the first time, every time.)
Thinking of Vernor Vinge's information archaeologists from A Fire Upon The Deep.
Breaking feature removal is more of the same spirit. These are the consequences of popularity and rapid progress. Perl would never be forced into a corner like this and chose to break things.
I’ve not used Perl as much in the last decade as I used to, but I’m always pleasantly surprised when I dig up some older stuff and it just works.
> The old regex and regsub modules, which have been deprecated ever since Python 2.0, have finally been deleted. Other deleted modules: statcache, tzparse, whrandom.
https://docs.python.org/3/whatsnew/2.5.html#new-improved-and...
Don’t get me wrong: there are plenty of things to dislike about it (or any language, once you start pulling that thread). However, they have made a much stronger commitment to avoid breaking backward compatibility.
I might be not as eager as some to learn new features though, but I am also not so conservative that I won't do things some new way, especially if the old way is being deprecated (but so far warnings have always given me plenty of heads up).
Quite the opposite, I like Python as much as I did when we first met. Nothing is without warts, but they are rarely really problematic for me in Python.
When you write code that has a short life span none of this matters. But when your software has a several year or decade life expectancy it will matter.
Also economics plays a role. If we have a real economic downturn in IT bit rot will become a huge problem for many small businesses.
What’s really funny is my older Python2 code doesn’t shit the bed half as much as the Python3 stuff due to it effectively being frozen in time.
Crypt is particularly painful, since removing it will effectively cryptoshred user password databases.
Anyway, I'm not particularly surprised. I don't think I've ever written or encountered a python script that didn't bit-rot after six months.
What do you mean by that? Anyone interacting with passwords on Linux, macOS, etc. has needed to use PAM anyway for decades. If you are building some kind of network app and just tossing passwords through crypt() you are going to have a much worse time on a security audit than you will installing a single python module.
I should look into which file formats are going away, I had some stuff that relied heavily on uuencode/decode (along with telnetlib) for bootstrapping file transfers into older systems…
A lot of that is code to interact with weird old shit, so I guess I can’t expect upstream to maintain old shit forever.
I do wish Python came with a solid cryptography library “out of the box” instead of having to use PyCrypto/Cryptodome/Cryptography/Whatever - and I also wish the way it’s ssl sockets module worked didn’t have weird unexpected things to do with how it handles file descriptors - you can’t just dup2 a ssl wrapped socket for example, unlike a normal socket
Unfortunately a lot of that old crusty shit is still in production in many places, despite being EoL for years, with no plans to replace it this side of 2038.
>>> from ctypes.util import find_library
>>> find_library("c")
'/usr/lib/libc.dylib'
>>> from ctypes import cdll
>>> libc = cdll.LoadLibrary(find_library("c"))
>>> import ctypes
>>> libc.crypt.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
>>> libc.crypt.restype = ctypes.c_char_p
>>> libc.crypt(b"toomanysecrets", b"az")
b'azi4LBG1VJohQ'
Here is what Python's own _crypt does: >>> import _crypt
>>> _crypt.crypt("toomanysecrets", "az")
'azi4LBG1VJohQ'"The original Enigma cipher was broken in 1944. The version implemented here is probably a good deal more difficult to crack (especially if you use many rotors), but it won't be impossible for a truly skillful and determined attacker to break the cipher. So if you want to keep the NSA out of your files, this rotor cipher may well be unsafe, but for discouraging casual snooping through your files, it will probably be just fine, and may be somewhat safer than using the Unix crypt command."
See https://docs.python.org/3/whatsnew/2.3.html for the deprecation notice: "The rotor module has been deprecated because the algorithm it uses for encryption is not believed to be secure. If you need encryption, use one of the several AES Python modules that are available separately."
"The algorithms are mostly old, of poor quality and insecure. Users are discouraged from using them."
Why is this post being upvoted?
2. No encryption in general, means also no http module, which means no REST calls, which means people would just use another language.
Technically yes, in the sense that libc also includes a libcrypt.so, but the one in glibc is hot garbage, so most distros disable the libcrypt part of glibc these days and ship libxcrypt instead.
Don’t do this. Instead, carefully analyse and evaluate well known and well tested packages to do crypto with.