我使用的是最新的Debian10。我对python crypt.crypt有意外的行为,一些调用引发了OSError: Invalid Argument异常,没有进一步的解释,所以我不太确定发生了什么。
>>> # debian - python3.9
>>> import crypt
>>> crypt.crypt("foo", '$2a$10$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.9/crypt.py", line 82, in crypt
return _crypt.crypt(word, salt)
OSError: [Errno 22] Invalid argument
>>> # archlinux - python3.9
>>> import crypt
>>> crypt.crypt("foo", '$2a$10$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7')
'$2a$10$Ud3Zhyb1M3I1PMDXWOFBp.8U7GsUrAN2JZZbKcxHSc.cTrK6oEA/.'这段代码在我的debian上用系统python3.7 (it returns None until python3.9)无声地失败了,并在我手动构建的python3.9上引发了这个OSError。在我的archlinux上,它在任何python版本上都能很好地工作。
edit1:我怀疑这是因为加密方法可能不再被debian支持了?
# On arch
>>> crypt.methods
[<crypt.METHOD_SHA512>, <crypt.METHOD_SHA256>, <crypt.METHOD_BLOWFISH>, <crypt.METHOD_MD5>, <crypt.METHOD_CRYPT>]
# On Debian
>>> crypt.methods
[<crypt.METHOD_SHA512>, <crypt.METHOD_SHA256>, <crypt.METHOD_MD5>, <crypt.METHOD_CRYPT>]edit2: crypt手册页显示了这段有趣的信息:
If salt is a character string starting with the characters "$id$" followed by a string
optionally terminated by "$", then the result has the form:
$id$salt$encrypted
id identifies the encryption method used instead of DES and this then determines how
the rest of the password string is interpreted.
The following values of id are supported:
ID | Method
─────────────────────────────────────────────────────────
1 | MD5
2a | Blowfish (not in mainline glibc; added in some
| Linux distributions)
5 | SHA-256 (since glibc 2.7)
6 | SHA-512 (since glibc 2.7)因此,盐开头的$2a意味着加密需要河豚才能正常工作,但根据crypt.method的说法,它在debian上不可用。
edit3:我可以用这段C代码来确认这一点
// gcc crypt.c -o foobar -lcrypt; ./foobar
#include <crypt.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main() {
char *crypt_result;
char* word = "foo";
char* salt = "$2a$10$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7";
crypt_result = crypt(word, salt);
if (crypt_result == NULL) {
printf("%s\n", strerror(errno));
}
else {
printf("%s\n", crypt_result);
}
return 0;
}它在archlinux上显示预期的输出,但在debian上显示Invalid argument。
我该如何解决这种情况?
发布于 2021-04-23 01:04:53
更多上下文
盐开头的$2a是blowfish/bcrypt方法的标记。
并非所有的Linux发行版都支持Blowfish,比如Ubuntu:
How to make Ubuntu's crypt(3) support Blowfish?
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1349252
从Debian 10开始,Debian不支持crypt中的blowfish,但在下一个版本中应该能够做到这一点,将crypt的依赖从glibc移动到libxcrypt:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=149452#42
https://blog.bofh.it/debian/id_458
如何解决这种情况
尝试使用passlib
我尝试将passlib与其原型类似于crypt.crypt的verify上下文一起使用
>>> from passlib.apps import custom_app_context as pwd_context
>>> pwd_context.verify("foo", '$2a$10$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7')但不幸的是,这段代码是seems to be bugged。
尝试使用bcrypt
现在,我将坚持使用crypt.crypt,并使用bcrypt作为后备:
import crypt
import bcrypt
def verify(password, hash):
try:
return crypt.crypt(password, hash) == hash
except OSError:
return bcrypt.checkpw(password.encode("utf-8"), hash.encode("utf-8"))
verify("foo", "$2a$10$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7")https://stackoverflow.com/questions/67216636
复制相似问题