crypt.crypt raises an OSError: Invalid Argument
crypt.crypt raises an OSError: Invalid Argument
我使用的是最新的 Debian 10。我在使用 python crypt.crypt
时出现意外行为,一些调用引发了 OSError: Invalid Argument
异常,没有进一步的解释,所以我不是真的确定发生了什么。
>>> # debian - python3.9
>>> import crypt
>>> crypt.crypt("foo", 'a$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", 'a$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7')
'a$Ud3Zhyb1M3I1PMDXWOFBp.8U7GsUrAN2JZZbKcxHSc.cTrK6oEA/.'
此代码在我的 debian 系统 python3.7 (it returns None
until python3.9) 上静默失败,并在我手动构建的 python3.9 上引发此 OSError
。它在我的任何 python 版本的 archlinux 上都运行良好。
edit1:我怀疑这是因为 debian 可能不再支持 crypt 方法?
# 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)
所以 salt 开头的 a
意味着 crypt 需要河豚才能正常工作,但根据 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 = "a$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
。
我该如何解决这种情况?
更多上下文
salt开头的a
是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 中的河豚,但应该能够在下一个版本中支持,将 crypt 的依赖项从 glibc 移至 libxcrypt:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=149452#42
https://blog.bofh.it/debian/id_458
如何解决这个问题
尝试使用 passlib
我尝试将 passlib 与 verify
上下文一起使用,其原型类似于 crypt.crypt
:
>>> from passlib.apps import custom_app_context as pwd_context
>>> pwd_context.verify("foo", 'a$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", "a$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7")
我使用的是最新的 Debian 10。我在使用 python crypt.crypt
时出现意外行为,一些调用引发了 OSError: Invalid Argument
异常,没有进一步的解释,所以我不是真的确定发生了什么。
>>> # debian - python3.9
>>> import crypt
>>> crypt.crypt("foo", 'a$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", 'a$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7')
'a$Ud3Zhyb1M3I1PMDXWOFBp.8U7GsUrAN2JZZbKcxHSc.cTrK6oEA/.'
此代码在我的 debian 系统 python3.7 (it returns None
until python3.9) 上静默失败,并在我手动构建的 python3.9 上引发此 OSError
。它在我的任何 python 版本的 archlinux 上都运行良好。
edit1:我怀疑这是因为 debian 可能不再支持 crypt 方法?
# 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)
所以 salt 开头的 a
意味着 crypt 需要河豚才能正常工作,但根据 crypt.method
.
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 = "a$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
。
我该如何解决这种情况?
更多上下文
salt开头的a
是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 中的河豚,但应该能够在下一个版本中支持,将 crypt 的依赖项从 glibc 移至 libxcrypt:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=149452#42
https://blog.bofh.it/debian/id_458
如何解决这个问题
尝试使用 passlib
我尝试将 passlib 与 verify
上下文一起使用,其原型类似于 crypt.crypt
:
>>> from passlib.apps import custom_app_context as pwd_context
>>> pwd_context.verify("foo", 'a$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", "a$Ud3Zhyb1M3I1PMDXWOFBp.81LKFwD5mZo33jnVHbPPrQY4cKSqoI7")