OSX中的python crypt

时间:2012-10-24 15:08:07

标签: python c encryption

我有一个Django应用程序,它重置在Ubuntu机器上运行的unix用户密码,但是我的开发环境是OS X,我遇到了这种烦人的情况:

OS X:

>>> import crypt
>>> crypt.crypt('test','$1$VFvON1xK$')
'$1SoNol0Ye6Xk'

Linux的:

>>> import crypt
>>> crypt.crypt('test','$1$VFvON1xK$')
'$1$VFvON1xK$SboCDZGBieKF1ns2GBfY50'

通过阅读crypt的pydoc,我看到它使用了特定于操作系统的crypt实现,因此我还在两个系统中测试了以下代码,结果与Python相同:

#include <unistd.h>

int main() {
        char *des = crypt("test","$1$VFvON1xK$ls4Zz4XTEuVI.1PnYm28.1");
        puts(des);
}

如何让OS X的crypt()实现生成与Linux crypt()相同的结果?
为什么Python实现没有涵盖这一点(正如我对跨平台部署的这种情况所期望的那样)?

3 个答案:

答案 0 :(得分:9)

这是因为Linux的glibc以不同的方式处理密码 - Linux上的密码盐对应于它生成的哈希类型。 OSX crypt()是普通的DES加密(这很可怕)。

glibc支持各种哈希算法(MD5,Blowfish,SHA-256等)。

如果我们查看crypt.3联机帮助页,我们可以看到:

   If salt is a character string starting with the characters "$id$" followed by
   a string terminated by "$":

          $id$salt$encrypted

   then instead of using the DES machine, id identifies the encryption method
   used 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)

所以,鉴于这些信息..让我们使用Linux的crypt

从第二个例子中获取你的密码
$1$VFvON1xK$SboCDZGBieKF1ns2GBfY50' ('test', encrypted with salt=VFvON1xK)


1                       == MD5
VFvON1xK                == Salt
SboCDZGBieKF1ns2GBfY50  == Hashed password

幸运的是,有一个跨平台的解决方案,passlib.hash.md5_crypt

以下是您使用它的方式:

from passlib.hash import md5_crypt
hash = md5_crypt.encrypt("test",salt="VFvON1xK")
print hash

在Linux或OSX上运行时,生成glibc友好密码哈希:

$1$VFvON1xK$SboCDZGBieKF1ns2GBfY50

与Linux机器上生成的原始文件相同。

答案 1 :(得分:5)

您将专门的salt字符串传递给函数,该函数调用Mac OS X上不可用的glibc特定的crypt行为。来自Debian 6上的crypt(3)手册页:

  

如果salt是以字符“$ id $”开头的字符串,后跟以“$”结尾的字符串...那么id不是使用DES机器,而是标识所使用的加密方法,然后确定如何其余的密码字符串被解释。

在你的python示例中,你告诉crypt使用id为1,这会导致使用MD5而不是基于DES的散列。在Mac OS X上没有这样的扩展,其中crypt严格基于DES。 (Mac OS X的crypt有自己的扩展 - salt可以是9个字符的数组,以下划线开头,后跟4个字节的迭代计数和4个字节的盐 - 在glibc中没有模拟实现。)

如果你避免在两个平台上使用crypt扩展并使用传统的crypt,其中salt只能是两个字节,那么你将从两个平台上的函数得到相同的结果,例如:

>>> crypt.crypt( "test", "S/" )
'S/AOO.b04HTR6'

从安全角度来看,这显然很糟糕。请考虑使用passlibpy-bcrypt之类的内容。任何一个都可以同时为您提供更好的散列和跨平台可靠性。

答案 2 :(得分:1)

为什么要在Python中使用单个crypt函数?如果你在OSX中运行,你需要osx版本crypt(),如果你在ubuntu中运行,它将使用ubuntu的crypt()。

这是一个跨平台的解决方案 - Python正在使用OS crypt来确保环境中的兼容性。如果Python使用它自己的crypt(),那么散列将是相同的 - 但它可以在OSX而不是Ubuntu(反之亦然)上工作

你可以写一些东西,或者找一个模块,重新实现crypt在每个环境中使用的哈希算法 - 但同样,这会破坏跨平台的目的。您将硬编码您的应用程序以使用Ubunutu,它可能使用不同的隐藏不仅来自OSX,而​​且来自其他Unix和BSD风格,如RedHat,FreeBSD等。