12

Ubuntu マシンで実行されている unix ユーザー パスワードをリセットする Django アプリケーションがありますが、私の開発環境は OS X であり、次の厄介な状況に遭遇しました。

OS X:

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

Linux:

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

の pydoc を読んだところcrypt、OS 固有のcrypt実装を使用していることがわかったので、両方のシステムで次のコードをテストし、Python と同じ結果を得ました。

#include <unistd.h>

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

crypt()OS X の実装で Linux と同じ結果を生成するにはどうすればよいcrypt()ですか?
そして、それが Python 実装でカバーされていないのはなぜですか (クロスプラットフォーム展開のそのようなケースから私が期待するように)?

4

4 に答える 4

15

これは、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の暗号を使用して2番目の例からパスワードを取得しましょう

$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 マシンで作成されたオリジナルと同一です。

于 2012-10-24T15:59:29.520 に答える
5

You're passing specialized salt strings to the function which invoke glibc-specific crypt behaviors that aren't available on Mac OS X. From the crypt(3) man page on Debian 6:

If salt is a character string starting with the characters "$id$" followed by a string terminated by "$"...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.

In your python examples, you're telling crypt to use an id of 1, which causes MD5 to be used instead of DES-based hashing. There's no such extension on Mac OS X, where crypt is strictly DES-based. (Mac OS X's crypt has its own extension--the salt can be a 9-character array, beginning with an underscore, followed by 4 bytes of iteration count and 4 bytes of salt--that has no analog in glibc's implementation.)

If you avoid the crypt extensions on both platforms and use traditional crypt, in which salt can only be two bytes, you'll get the same results from the function on both platforms, e.g.:

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

That's obviously terrible from a security perspective. Consider using something like passlib or py-bcrypt instead. Either one will get you vastly better hashing and cross-platform reliability at the same time.

于 2012-10-24T16:03:10.207 に答える
2

Python で単一の crypt 関数が必要な理由は何ですか? OSX で実行している場合は、osx バージョンの crypt() が必要です。ubuntu で実行している場合は、ubuntu の crypt() を使用します。

これはクロス プラットフォーム ソリューションです。Python は OS crypt を使用して、環境内での互換性を確保しています。Python が独自の crypt() を使用した場合、ハッシュは同じになりますが、Ubuntu ではなく OSX で動作します (またはその逆)。

crypt が各環境で使用するハッシュ アルゴリズムを再実装する何かを作成したり、モジュールを見つけたりすることはできますが、これもまた、クロス プラットフォームであるという目的に反することになります。OSX だけでなく、RedHat、FreeBSD などの他の Unix および BSD フレーバーからの異なる暗号を使用する可能性がある Ubunutu で動作するようにアプリをハードコーディングします。

于 2012-10-24T15:29:19.400 に答える