summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/contents.rst2
-rw-r--r--docs/copyright.rst6
-rw-r--r--docs/index.rst2
-rw-r--r--docs/install.rst2
-rw-r--r--docs/lib/passlib.hash.rst24
-rw-r--r--docs/lib/passlib.hash/algorithms.rst4
-rw-r--r--docs/lib/passlib.hash/contexts.rst4
-rw-r--r--docs/lib/passlib.hash/implementation.rst4
-rw-r--r--docs/lib/passlib.hash/quickstart.rst4
-rw-r--r--docs/lib/passlib.hash/utils.rst4
-rw-r--r--[-rwxr-xr-x]passlib/__init__.py150
-rw-r--r--passlib/_slow_bcrypt.py (renamed from passlib/hash/_slow_bcrypt.py)2
-rw-r--r--passlib/_slow_unix_crypt.py (renamed from passlib/hash/_slow_unix_crypt.py)0
-rw-r--r--passlib/base.py (renamed from passlib/hash/base.py)16
-rw-r--r--passlib/bcrypt.py (renamed from passlib/hash/bcrypt.py)7
-rw-r--r--passlib/gen.py2
-rw-r--r--passlib/hash/__init__.py150
-rw-r--r--passlib/md5_crypt.py (renamed from passlib/hash/md5_crypt.py)4
-rw-r--r--passlib/mysql.py (renamed from passlib/hash/mysql.py)8
-rw-r--r--passlib/pbkdf2.py (renamed from passlib/hash/pbkdf2.py)0
-rw-r--r--passlib/postgres.py (renamed from passlib/hash/postgres.py)4
-rw-r--r--passlib/sha_crypt.py (renamed from passlib/hash/sha_crypt.py)12
-rw-r--r--passlib/tests/test_base.py (renamed from passlib/tests/test_hash_base.py)2
-rw-r--r--passlib/tests/test_base_context.py (renamed from passlib/tests/test_crypt_context.py)39
-rwxr-xr-xpasslib/tests/test_bcrypt.py (renamed from passlib/tests/test_hash_bcrypt.py)6
-rw-r--r--passlib/tests/test_frontend.py (renamed from passlib/tests/test_hash_frontend.py)48
-rw-r--r--passlib/tests/test_md5_crypt.py (renamed from passlib/tests/test_hash_md5_crypt.py)5
-rw-r--r--passlib/tests/test_mysql.py (renamed from passlib/tests/test_hash_mysql.py)5
-rw-r--r--passlib/tests/test_pbkdf2.py (renamed from passlib/tests/test_hash_pbkdf2.py)6
-rw-r--r--passlib/tests/test_postgres.py (renamed from passlib/tests/test_hash_postgres.py)5
-rw-r--r--passlib/tests/test_sha_crypt.py (renamed from passlib/tests/test_hash_sha_crypt.py)7
-rw-r--r--passlib/tests/test_unix_crypt.py (renamed from passlib/tests/test_hash_unix_crypt.py)8
-rw-r--r--passlib/unix_crypt.py (renamed from passlib/hash/unix_crypt.py)4
-rw-r--r--passlib/util.py6
34 files changed, 276 insertions, 276 deletions
diff --git a/docs/contents.rst b/docs/contents.rst
index 44f46b3..dd4ceb4 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -9,7 +9,7 @@ Table Of Contents
overview
lib/passlib
- lib/passlib.hash
+ lib/passlib
lib/passlib.gen
lib/passlib.util
diff --git a/docs/copyright.rst b/docs/copyright.rst
index ee19414..fc2c6ac 100644
--- a/docs/copyright.rst
+++ b/docs/copyright.rst
@@ -53,7 +53,7 @@ implementation of OpenBSD's BCrypt algorithm, written by Damien Miller,
and released under a BSD license.
:mod:`passlib._bcrypt` is a python translation of this code,
-which is used as a fallback backend for :class:`passlib.hash.BCrypt`
+which is used as a fallback backend for :class:`passlib.BCrypt`
when the external python library `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_
is not installed.
@@ -75,7 +75,7 @@ This is the license and copyright for jBCrypt::
MD5-Crypt
---------
-The class :class:`passlib.hash.Md5Crypt` is a pure-python
+The class :class:`passlib.Md5Crypt` is a pure-python
implementation of the md5-crypt password hashing algorithm.
It's derived from the FreeBSD md5-crypt implementation `<http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libcrypt/crypt.c?rev=1.2>`_,
which was released under the following license::
@@ -93,7 +93,7 @@ Originally written by Aki Yoshida, and modified by others,
it was released under a BSD-like license.
:mod:`passlib._unix_crypt` is a python translation of this code,
-which is used as a fallback backend for :class:`passlib.hash.UnixCrypt`
+which is used as a fallback backend for :class:`passlib.UnixCrypt`
for platforms where stdlib's :mod:`crypt` is not available.
This is the license and copyright for UnixCrypt.java::
diff --git a/docs/index.rst b/docs/index.rst
index 8e501f1..821ee65 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,7 +14,7 @@ A quick sample of some of the more frequently used modules:
* :mod:`bps.host` -- desktop and host resources
* :mod:`bps.logs` -- enhancements to Python's logging system
* :mod:`bps.text` -- text parsing and formatting
- * :mod:`passlib.hash` -- password hashing algorithms
+ * :mod:`passlib` -- password hashing algorithms
... see the :doc:`library overview <overview>` for a complete list.
diff --git a/docs/install.rst b/docs/install.rst
index 8204e1f..1b29858 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -19,7 +19,7 @@ The following libraries will be used if present, but they are not required:
* If installed, `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_ will be
used instead of PassLib's slower pure-python bcrypt implementation.
- (see :class:`passlib.hash.BCrypt`).
+ (see :class:`passlib.BCrypt`).
Installing
==========
diff --git a/docs/lib/passlib.hash.rst b/docs/lib/passlib.hash.rst
index 0f2bfb0..621ed0d 100644
--- a/docs/lib/passlib.hash.rst
+++ b/docs/lib/passlib.hash.rst
@@ -1,8 +1,8 @@
=============================================
-:mod:`passlib.hash` - Password Hashing
+:mod:`passlib` - Password Hashing
=============================================
-.. module:: passlib.hash
+.. module:: passlib
:synopsis: password hashing (unix-crypt, md5-crypt, etc)
Overview
@@ -28,17 +28,17 @@ Sections
========
The documentation for the pwhash module is broken into the following sections:
-* :doc:`Quick Start <passlib.hash/quickstart>` -- frontend funcs for quickly creating / validating hashes
-* :doc:`Crypt Contexts <passlib.hash/contexts>` -- for using just the algorithms your application needs
-* :doc:`Crypt Algorithms <passlib.hash/algorithms>` -- details of the algorithms BPS implements
-* :doc:`Implementing a Custom Crypt Algorithm <passlib.hash/implementation>` -- Roll your own
-* :doc:`Helper Functions <passlib.hash/utils>`
+* :doc:`Quick Start <passlib/quickstart>` -- frontend funcs for quickly creating / validating hashes
+* :doc:`Crypt Contexts <passlib/contexts>` -- for using just the algorithms your application needs
+* :doc:`Crypt Algorithms <passlib/algorithms>` -- details of the algorithms BPS implements
+* :doc:`Implementing a Custom Crypt Algorithm <passlib/implementation>` -- Roll your own
+* :doc:`Helper Functions <passlib/utils>`
.. toctree::
:hidden:
- passlib.hash/quickstart
- passlib.hash/contexts
- passlib.hash/algorithms
- passlib.hash/implementation
- passlib.hash/utils
+ passlib/quickstart
+ passlib/contexts
+ passlib/algorithms
+ passlib/implementation
+ passlib/utils
diff --git a/docs/lib/passlib.hash/algorithms.rst b/docs/lib/passlib.hash/algorithms.rst
index 730743f..acb28f5 100644
--- a/docs/lib/passlib.hash/algorithms.rst
+++ b/docs/lib/passlib.hash/algorithms.rst
@@ -1,8 +1,8 @@
=============================================
-:mod:`passlib.hash` - Crypt Algorithms
+:mod:`passlib` - Crypt Algorithms
=============================================
-.. currentmodule:: passlib.hash
+.. currentmodule:: passlib
All of the crypt algorithms must inherit from :class:`CryptAlgorithm`,
which defines a common interface all algorithms must support.
diff --git a/docs/lib/passlib.hash/contexts.rst b/docs/lib/passlib.hash/contexts.rst
index 3718df3..aa463f9 100644
--- a/docs/lib/passlib.hash/contexts.rst
+++ b/docs/lib/passlib.hash/contexts.rst
@@ -1,8 +1,8 @@
=============================================
-:mod:`passlib.hash` - Crypt Contexts
+:mod:`passlib` - Crypt Contexts
=============================================
-.. currentmodule:: passlib.hash
+.. currentmodule:: passlib
For more complex deployment scenarios than
the frontend functions described in :doc:`Quick Start <quickstart>`,
diff --git a/docs/lib/passlib.hash/implementation.rst b/docs/lib/passlib.hash/implementation.rst
index 7f603c9..4ea6e24 100644
--- a/docs/lib/passlib.hash/implementation.rst
+++ b/docs/lib/passlib.hash/implementation.rst
@@ -1,8 +1,8 @@
===================================================================
-:mod:`passlib.hash` - Implementing a Custom Crypt Algorithm
+:mod:`passlib` - Implementing a Custom Crypt Algorithm
===================================================================
-.. currentmodule:: passlib.hash
+.. currentmodule:: passlib
New password algorithms can be implemented
by subclassing :class:`CryptAlgorithm`,
diff --git a/docs/lib/passlib.hash/quickstart.rst b/docs/lib/passlib.hash/quickstart.rst
index 94bc40d..c6128f8 100644
--- a/docs/lib/passlib.hash/quickstart.rst
+++ b/docs/lib/passlib.hash/quickstart.rst
@@ -1,8 +1,8 @@
========================================
-:mod:`passlib.hash` - Quick Start
+:mod:`passlib` - Quick Start
========================================
-.. currentmodule:: passlib.hash
+.. currentmodule:: passlib
Usage Example
=============
diff --git a/docs/lib/passlib.hash/utils.rst b/docs/lib/passlib.hash/utils.rst
index 345e80b..4da7d54 100644
--- a/docs/lib/passlib.hash/utils.rst
+++ b/docs/lib/passlib.hash/utils.rst
@@ -1,8 +1,8 @@
=============================================
-:mod:`passlib.hash` - Helper Functions
+:mod:`passlib` - Helper Functions
=============================================
-.. currentmodule:: passlib.hash
+.. currentmodule:: passlib
A couple of utility functions are available,
mainly useful when writing custom password hash algorithms.
diff --git a/passlib/__init__.py b/passlib/__init__.py
index 8e577de..2d8974f 100755..100644
--- a/passlib/__init__.py
+++ b/passlib/__init__.py
@@ -1,2 +1,152 @@
"""passlib - suite of password hashing & generation routinges"""
+
__version__ = "1.1"
+
+from passlib.base import CryptContext
+import passlib.unix_crypt
+import passlib.md5_crypt
+import passlib.bcrypt
+import passlib.sha_crypt
+
+#=========================================================
+#build up the standard context objects
+#=========================================================
+
+#default context for quick use.. recognizes common algorithms, uses SHA-512 as default
+default_context = CryptContext(["unix-crypt", "md5-crypt", "bcrypt", "sha256-crypt", "sha512-crypt"])
+
+def identify(hash, name=True):
+ """Identify algorithm which generated a password hash.
+
+ :arg hash:
+ The hash string to identify.
+ :param name:
+ If ``True``, this function will return a name identifying the hash algorithm (the default).
+ If ``False``, it will return the handler object associated with that algorithm.
+
+ The following algorithms are currently recognized:
+
+ =================== ================================================
+ Name Description
+ ------------------- ------------------------------------------------
+ ``"unix-crypt"`` the historical unix-crypt algorithm
+
+ ``"md5-crypt"`` the md5-crypt algorithm, usually identified
+ by the prefix ``$1$`` in unix shadow files.
+
+ ``"bcrypt"`` the openbsd blowfish-crypt algorithm,
+ usually identified by the prefixes ``$2$`` or ``$2a$``
+ in unix shadow files.
+
+ ``"sha256-crypt"`` the 256-bit version of the sha-crypt algorithm,
+ usually identified by the prefix ``$5$``
+ in unix shadow files.
+
+ ``"sha512-crypt"`` the 512-bit version of the sha-crypt algorithm,
+ usually identified by the prefix ``$6$``
+ in unix shadow files.
+ =================== ================================================
+
+ :returns:
+ The name of the hash, or ``None`` if the hash could not be identified.
+ (The return may be altered by the *resolve* keyword).
+
+ .. note::
+ This is a convience wrapper for ``pwhash.default_context.identify(hash)``.
+ """
+ return default_context.identify(hash, name=name)
+
+def encrypt(secret, hash=None, alg=None, **kwds):
+ """Encrypt secret using a password hash algorithm.
+
+ :type secret: str
+ :arg secret:
+ String containing the secret to encrypt
+
+ :type hash: str|None
+ :arg hash:
+ Optional previously existing hash string which
+ will be used to provide default value for the salt, rounds,
+ or other algorithm-specific options.
+ If not specified, algorithm-chosen defaults will be used.
+
+ :type alg: str|None
+ :param alg:
+ Optionally specify the name of the algorithm to use.
+ If no algorithm is specified, an attempt is made
+ to guess from the hash string. If no hash string
+ is specified, sha512-crypt will be used.
+ See :func:`identify` for a list of algorithm names.
+
+ All other keywords are passed on to the specific password algorithm
+ being used to encrypt the secret.
+
+ :type keep_salt: bool
+ :param keep_salt:
+ This option is accepted by all of the builtin algorithms.
+
+ By default, a new salt value generated each time
+ a secret is encrypted. However, if this keyword
+ is set to ``True``, and a previous hash string is provided,
+ the salt from that string will be used instead.
+
+ .. note::
+ This is generally only useful when verifying an existing hash
+ (see :func:`verify`). Other than that, this option should be
+ avoided, as re-using a salt will needlessly decrease security.
+
+ :type rounds: int
+ :param rounds:
+ For the sha256-crypt and sha512-crypt algorithms,
+ this option lets you specify the number of rounds
+ of encryption to use. For the bcrypt algorithm,
+ this option lets you specify the log-base-2 of
+ the number of rounds of encryption to use.
+
+ For all three of these algorithms, you can either
+ specify a positive integer, or one of the strings
+ "fast", "medium", "slow" to choose a preset number
+ of rounds corresponding to an appropriate level
+ of encryption.
+
+ :returns:
+ The secret as encoded by the specified algorithm and options.
+ """
+ return default_context.encrypt(secret, hash=hash, alg=alg, **kwds)
+
+def verify(secret, hash, alg=None):
+ """verify a secret against an existing hash.
+
+ This checks if a secret matches against the one stored
+ inside the specified hash. By default this uses :func:`encrypt`
+ to re-crypt the secret, and compares it to the provided hash;
+ though some algorithms may implement this in a more efficient manner.
+
+ :type secret: str
+ :arg secret:
+ A string containing the secret to check.
+
+ :type hash: str
+ :param hash:
+ A string containing the hash to check against.
+
+ :type alg: str|None
+ :param alg:
+ Optionally specify the name of the algorithm to use.
+ If no algorithm is specified, an attempt is made
+ to guess from the hash string. If it can't be
+ identified, a ValueError will be raised.
+ See :func:`identify` for a list of algorithm names.
+
+ :returns:
+ ``True`` if the secret matches, otherwise ``False``.
+ """
+ return default_context.verify(secret, hash, alg=alg)
+
+#some general os-context helpers (these may not match your os policy exactly, but are generally useful)
+linux_context = CryptContext([ "unix-crypt", "md5-crypt", "sha256-crypt", "sha512-crypt" ])
+bsd_context = CryptContext([ "unix-crypt", "md5-crypt", "bcrypt" ])
+
+#=========================================================
+#eof
+#=========================================================
diff --git a/passlib/hash/_slow_bcrypt.py b/passlib/_slow_bcrypt.py
index 2606b2e..147ae2e 100644
--- a/passlib/hash/_slow_bcrypt.py
+++ b/passlib/_slow_bcrypt.py
@@ -1,4 +1,4 @@
-"""passlib.hash._slow_bcrypt - fallback pure-python bcrypt implementation
+"""passlib._slow_bcrypt - fallback pure-python bcrypt implementation
History
==========
diff --git a/passlib/hash/_slow_unix_crypt.py b/passlib/_slow_unix_crypt.py
index f2d738f..f2d738f 100644
--- a/passlib/hash/_slow_unix_crypt.py
+++ b/passlib/_slow_unix_crypt.py
diff --git a/passlib/hash/base.py b/passlib/base.py
index fca174d..46af8ad 100644
--- a/passlib/hash/base.py
+++ b/passlib/base.py
@@ -1,4 +1,4 @@
-"""passlib.hash - implementation of various password hashing functions"""
+"""passlib - implementation of various password hashing functions"""
#=========================================================
#imports
#=========================================================
@@ -235,7 +235,7 @@ class CryptAlgorithm(object):
Usage Example::
- >>> from passlib.hash.md5_crypt import Md5Crypt
+ >>> from passlib.md5_crypt import Md5Crypt
>>> #encrypt a secret, creating a new hash
>>> hash = Md5Crypt.encrypt("it's a secret")
>>> hash
@@ -367,7 +367,7 @@ class CryptContext(object):
'bcrypt'
>>> #or just return the CryptAlgorithm instance directly
>>> myctx.identify(hash1, resolve=True)
- <passlib.hash.BCrypt object, name="bcrypt">
+ <passlib.BCrypt object, name="bcrypt">
>>> #you can get a list of algs...
>>> myctx.keys()
@@ -376,7 +376,7 @@ class CryptContext(object):
>>> #and get the CryptAlgorithm object by name
>>> bc = myctx['bcrypt']
>>> bc
- <passlib.hash.BCrypt object, name="bcrypt">
+ <passlib.BCrypt object, name="bcrypt">
"""
def __init__(self, handlers):
@@ -384,7 +384,7 @@ class CryptContext(object):
def _norm_handler(self, handler):
if isinstance(handler, str):
- handler = get_crypto_algorithm(handler)
+ handler = get_crypt_algorithm(handler)
if not is_crypt_alg(handler):
raise TypeError, "handler must be CryptAlgorithm class or name: %r" % (handler,)
return handler
@@ -412,7 +412,7 @@ class CryptContext(object):
if name in handler.aliases:
return handler
else:
- return self._args[-1]
+ return self._handlers[-1]
if required:
raise KeyError, "no crypt algorithm by that name in context: %r" % (name,)
return None
@@ -442,7 +442,7 @@ class CryptContext(object):
# also so if handler 0 is a legacy "plaintext" handler or some such,
# it doesn't match *everything* that's passed into this function.
for handler in reversed(self._handlers):
- if handlers.identify(hash):
+ if handler.identify(hash):
if name:
return handler.name
else:
@@ -501,7 +501,7 @@ class CryptContext(object):
handler = self.lookup(alg, required=True)
else:
handler = self.identify(hash, required=True)
- return crypt.verify(secret, hash, **kwds)
+ return handler.verify(secret, hash, **kwds)
def is_crypt_context(obj):
"check if obj following CryptContext protocol"
diff --git a/passlib/hash/bcrypt.py b/passlib/bcrypt.py
index 6fa07ee..79604ae 100644
--- a/passlib/hash/bcrypt.py
+++ b/passlib/bcrypt.py
@@ -1,4 +1,4 @@
-"""passlib.hash.bcrypt"""
+"""passlib.bcrypt"""
#=========================================================
#imports
#=========================================================
@@ -9,7 +9,7 @@ import logging; log = logging.getLogger(__name__)
#site
#libs
from passlib.util import HashInfo, h64_gensalt
-from passlib.hash.base import CryptAlgorithm, register_crypt_algorithm
+from passlib.base import CryptAlgorithm, register_crypt_algorithm
#pkg
#local
__all__ = [
@@ -26,7 +26,7 @@ try:
backend = "pybcrypt"
except ImportError:
#fall back to our much slower pure-python implementation
- import passlib.hash._slow_bcrypt as bcrypt
+ import passlib._slow_bcrypt as bcrypt
backend = "builtin"
#=========================================================
@@ -118,7 +118,6 @@ class BCrypt(CryptAlgorithm):
if not salt:
salt = h64_gensalt(22)
enc_salt = "$2a$%d$%s" % (rounds, salt)
- print repr([secret, enc_salt])
return bcrypt.hashpw(secret, enc_salt)
@classmethod
diff --git a/passlib/gen.py b/passlib/gen.py
index fdf0693..bbb27a1 100644
--- a/passlib/gen.py
+++ b/passlib/gen.py
@@ -1,4 +1,4 @@
-"""passlib.hash - password hashing tools"""
+"""passlib - password hashing tools"""
#=========================================================
#imports
#=========================================================
diff --git a/passlib/hash/__init__.py b/passlib/hash/__init__.py
deleted file mode 100644
index aa547cc..0000000
--- a/passlib/hash/__init__.py
+++ /dev/null
@@ -1,150 +0,0 @@
-from passlib.hash.base import CryptContext
-import passlib.hash.unix_crypt
-import passlib.hash.md5_crypt
-import passlib.hash.bcrypt
-import passlib.hash.sha_crypt
-
-#=========================================================
-#build up the standard context objects
-#=========================================================
-
-#default context for quick use.. recognizes common algorithms, uses SHA-512 as default
-default_context = CryptContext(["unix-crypt", "md5-crypt", "bcrypt", "sha256-crypt", "sha512-crypt"])
-
-def identify(hash, name=name):
- """Identify algorithm which generated a password hash.
-
- :arg hash:
- The hash string to identify.
- :param resolve:
- If ``True``, this function will return a :class:`CryptAlgorithm`
- instance which can handle the hash.
- If ``False`` (the default), then only the name of the hash algorithm
- will be returned.
-
- The following algorithms are currently recognized:
-
- =================== ================================================
- Name Description
- ------------------- ------------------------------------------------
- ``"unix-crypt"`` the historical unix-crypt algorithm
-
- ``"md5-crypt"`` the md5-crypt algorithm, usually identified
- by the prefix ``$1$`` in unix shadow files.
-
- ``"bcrypt"`` the openbsd blowfish-crypt algorithm,
- usually identified by the prefixes ``$2$`` or ``$2a$``
- in unix shadow files.
-
- ``"sha256-crypt"`` the 256-bit version of the sha-crypt algorithm,
- usually identified by the prefix ``$5$``
- in unix shadow files.
-
- ``"sha512-crypt"`` the 512-bit version of the sha-crypt algorithm,
- usually identified by the prefix ``$6$``
- in unix shadow files.
- =================== ================================================
-
- :returns:
- The name of the hash, or ``None`` if the hash could not be identified.
- (The return may be altered by the *resolve* keyword).
-
- .. note::
- This is a convience wrapper for ``pwhash.default_context.identify(hash)``.
- """
- return default_context.identify(hash, name=name)
-
-def encrypt(secret, hash=None, alg=None, **kwds):
- """Encrypt secret using a password hash algorithm.
-
- :type secret: str
- :arg secret:
- String containing the secret to encrypt
-
- :type hash: str|None
- :arg hash:
- Optional previously existing hash string which
- will be used to provide default value for the salt, rounds,
- or other algorithm-specific options.
- If not specified, algorithm-chosen defaults will be used.
-
- :type alg: str|None
- :param alg:
- Optionally specify the name of the algorithm to use.
- If no algorithm is specified, an attempt is made
- to guess from the hash string. If no hash string
- is specified, sha512-crypt will be used.
- See :func:`identify` for a list of algorithm names.
-
- All other keywords are passed on to the specific password algorithm
- being used to encrypt the secret.
-
- :type keep_salt: bool
- :param keep_salt:
- This option is accepted by all of the builtin algorithms.
-
- By default, a new salt value generated each time
- a secret is encrypted. However, if this keyword
- is set to ``True``, and a previous hash string is provided,
- the salt from that string will be used instead.
-
- .. note::
- This is generally only useful when verifying an existing hash
- (see :func:`verify`). Other than that, this option should be
- avoided, as re-using a salt will needlessly decrease security.
-
- :type rounds: int
- :param rounds:
- For the sha256-crypt and sha512-crypt algorithms,
- this option lets you specify the number of rounds
- of encryption to use. For the bcrypt algorithm,
- this option lets you specify the log-base-2 of
- the number of rounds of encryption to use.
-
- For all three of these algorithms, you can either
- specify a positive integer, or one of the strings
- "fast", "medium", "slow" to choose a preset number
- of rounds corresponding to an appropriate level
- of encryption.
-
- :returns:
- The secret as encoded by the specified algorithm and options.
- """
- return default_context.encrypt(secret, hash=hash, alg=alg, **kwds)
-
-def verify(secret, hash, alg=None):
- """verify a secret against an existing hash.
-
- This checks if a secret matches against the one stored
- inside the specified hash. By default this uses :func:`encrypt`
- to re-crypt the secret, and compares it to the provided hash;
- though some algorithms may implement this in a more efficient manner.
-
- :type secret: str
- :arg secret:
- A string containing the secret to check.
-
- :type hash: str
- :param hash:
- A string containing the hash to check against.
-
- :type alg: str|None
- :param alg:
- Optionally specify the name of the algorithm to use.
- If no algorithm is specified, an attempt is made
- to guess from the hash string. If it can't be
- identified, a ValueError will be raised.
- See :func:`identify` for a list of algorithm names.
-
- :returns:
- ``True`` if the secret matches, otherwise ``False``.
- """
- return default_context.verify(secret, hash, alg=alg)
-
-#some general os-context helpers (these may not match your os policy exactly, but are generally useful)
-linux_context = CryptContext([ "unix-crypt", "md5-crypt", "sha256-crypt", "sha512-crypt" ])
-bsd_context = CryptContext([ "unix-crypt", "md5-crypt", "bcrypt" ])
-
-#=========================================================
-#eof
-#=========================================================
diff --git a/passlib/hash/md5_crypt.py b/passlib/md5_crypt.py
index b48f5b4..4335542 100644
--- a/passlib/hash/md5_crypt.py
+++ b/passlib/md5_crypt.py
@@ -1,4 +1,4 @@
-"""passlib.hash - implementation of various password hashing functions"""
+"""passlib - implementation of various password hashing functions"""
#=========================================================
#imports
#=========================================================
@@ -14,7 +14,7 @@ import os
#libs
from passlib.util import classproperty, abstractmethod, is_seq, srandom, \
HashInfo, h64_gensalt, h64_encode_3_offsets, h64_encode_1_offset
-from passlib.hash.base import CryptAlgorithm, register_crypt_algorithm
+from passlib.base import CryptAlgorithm, register_crypt_algorithm
#pkg
#local
__all__ = [
diff --git a/passlib/hash/mysql.py b/passlib/mysql.py
index aeef333..a00e454 100644
--- a/passlib/hash/mysql.py
+++ b/passlib/mysql.py
@@ -1,4 +1,4 @@
-"""passlib.hash - implementation of various password hashing functions"""
+"""passlib - implementation of various password hashing functions"""
#=========================================================
#imports
#=========================================================
@@ -13,7 +13,7 @@ import os
#site
#libs
from passlib.util import classproperty, abstractmethod, is_seq, srandom
-from passlib.hash.base import CryptAlgorithm, CryptContext, register_crypt_algorithm
+from passlib.base import CryptAlgorithm, CryptContext, register_crypt_algorithm
#pkg
#local
__all__ = [
@@ -36,7 +36,7 @@ class Mysql10Crypt(CryptAlgorithm):
and should only be used to verify existing password hashes.
"""
- name = "mysql-1.0-crypt"
+ name = "mysql-10-crypt"
hash_bytes = 32
_pat = re.compile(r"^[0-9a-f]{16}$", re.I)
@@ -78,7 +78,7 @@ class Mysql41Crypt(CryptAlgorithm):
Description taken from http://dev.mysql.com/doc/refman/6.0/en/password-hashing.html
"""
- name = "mysql-4.1-crypt"
+ name = "mysql-41-crypt"
hash_bytes = 80
_pat = re.compile(r"^\*[0-9A-F]{40}$", re.I)
diff --git a/passlib/hash/pbkdf2.py b/passlib/pbkdf2.py
index 016023b..016023b 100644
--- a/passlib/hash/pbkdf2.py
+++ b/passlib/pbkdf2.py
diff --git a/passlib/hash/postgres.py b/passlib/postgres.py
index 3054b99..e526e75 100644
--- a/passlib/hash/postgres.py
+++ b/passlib/postgres.py
@@ -1,4 +1,4 @@
-"""passlib.hash - implementation of various password hashing functions"""
+"""passlib - implementation of various password hashing functions"""
#=========================================================
#imports
#=========================================================
@@ -13,7 +13,7 @@ import os
#site
#libs
from passlib.util import classproperty, abstractmethod, is_seq, srandom
-from passlib.hash.base import CryptAlgorithm, CryptContext, register_crypt_algorithm
+from passlib.base import CryptAlgorithm, CryptContext, register_crypt_algorithm
#pkg
#local
__all__ = [
diff --git a/passlib/hash/sha_crypt.py b/passlib/sha_crypt.py
index 5c17e30..4263683 100644
--- a/passlib/hash/sha_crypt.py
+++ b/passlib/sha_crypt.py
@@ -1,4 +1,4 @@
-"""passlib.hash.sha_crypt - implements SHA-256-Crypt & SHA-512-Crypt
+"""passlib.sha_crypt - implements SHA-256-Crypt & SHA-512-Crypt
Implementation written based on specification at `<http://www.akkadia.org/drepper/SHA-crypt.txt>`_.
It should be byte-compatible with unix shadow hashes beginning with ``$5$`` and ``$6%``.
@@ -21,9 +21,9 @@ import time
import os
#site
#libs
-from passlib.hash.base import CryptAlgorithm, register_crypt_algorithm
+from passlib.base import CryptAlgorithm, register_crypt_algorithm
from passlib.util import classproperty, abstractmethod, is_seq, srandom, \
- HashInfo, h64_gensalt, h64_encode_3_offsets, h64_encode_2_offsets
+ HashInfo, h64_gensalt, h64_encode_3_offsets, h64_encode_2_offsets, h64_encode_1_offset
#pkg
#local
__all__ = [
@@ -241,7 +241,7 @@ class Sha256Crypt(_ShaCrypt):
#=========================================================
#algorithm info
#=========================================================
- name='sha-256-crypt'
+ name='sha256-crypt'
hash_bytes = 32
#=========================================================
@@ -297,7 +297,7 @@ class Sha512Crypt(_ShaCrypt):
Usage Example::
- >>> from passlib.hash import Sha512Crypt
+ >>> from passlib import Sha512Crypt
>>> crypt = Sha512Crypt()
>>> #to encrypt a new secret with this algorithm
>>> hash = crypt.encrypt("forget me not")
@@ -314,7 +314,7 @@ class Sha512Crypt(_ShaCrypt):
#=========================================================
#algorithm info
#=========================================================
- name='sha-512-crypt'
+ name='sha512-crypt'
hash_bytes = 64
#=========================================================
diff --git a/passlib/tests/test_hash_base.py b/passlib/tests/test_base.py
index aa50898..70e50ea 100644
--- a/passlib/tests/test_hash_base.py
+++ b/passlib/tests/test_base.py
@@ -9,7 +9,7 @@ import warnings
from logging import getLogger
#site
#pkg
-from passlib.hash.base import CryptAlgorithm
+from passlib.base import CryptAlgorithm
from passlib.tests.utils import TestCase, enable_suite
from passlib.util import h64_gensalt
#module
diff --git a/passlib/tests/test_crypt_context.py b/passlib/tests/test_base_context.py
index 174b4ea..7526efd 100644
--- a/passlib/tests/test_crypt_context.py
+++ b/passlib/tests/test_base_context.py
@@ -9,21 +9,18 @@ import warnings
from logging import getLogger
#site
#pkg
-from passlib import hash as pwhash
+from passlib.base import CryptContext
from passlib.tests.utils import TestCase, enable_suite
-from passlib.hash.unix_crypt import UnixCrypt
-from passlib.hash.sha_crypt import Sha512Crypt
-from passlib.hash.md5_crypt import Md5Crypt
-from passlib.tests.test_hash_base import UnsaltedAlg, SaltedAlg, SampleAlg
+from passlib.unix_crypt import UnixCrypt
+from passlib.sha_crypt import Sha512Crypt
+from passlib.md5_crypt import Md5Crypt
+from passlib.tests.test_base import UnsaltedAlg, SaltedAlg, SampleAlg
#module
log = getLogger(__name__)
#=========================================================
#CryptContext
#=========================================================
-
-CryptContext = pwhash.CryptContext
-
class CryptContextTest(TestCase):
"test CryptContext object's behavior"
@@ -36,10 +33,10 @@ class CryptContextTest(TestCase):
cc = CryptContext([UnsaltedAlg, SaltedAlg, SampleAlg])
#parse
- a, b, c = cc
- self.assertIsInstance(a, UnsaltedAlg)
- self.assertIsInstance(b, SaltedAlg)
- self.assertIsInstance(c, SampleAlg)
+ a, b, c = cc._handlers
+ self.assertIs(a, UnsaltedAlg)
+ self.assertIs(b, SaltedAlg)
+ self.assertIs(c, SampleAlg)
def test_01_constructor(self):
"test CryptContext constructor using instances"
@@ -50,7 +47,7 @@ class CryptContextTest(TestCase):
cc = CryptContext([a,b,c])
#verify elements
- self.assertEquals(list(cc), [a, b, c])
+ self.assertEquals(list(cc._handlers), [a, b, c])
#TODO: test constructor using names
@@ -356,23 +353,23 @@ class CryptContextTest(TestCase):
def test_50_lookup(self):
"test CryptContext.lookup()"
cc = CryptContext([UnsaltedAlg, SaltedAlg, SampleAlg])
- a, b, c = cc
+ a, b, c = cc._handlers
self.assertEquals(cc.lookup('unsalted'), a)
self.assertEquals(cc.lookup('salted'), b)
self.assertEquals(cc.lookup('sample'), c)
self.assertEquals(cc.lookup('md5-crypt'), None)
- self.assertEquals(cc.lookup(['unsalted']), a)
- self.assertEquals(cc.lookup(['md5-crypt']), None)
- self.assertEquals(cc.lookup(['unsalted', 'salted', 'md5-crypt']), b)
+ ##self.assertEquals(cc.lookup(['unsalted']), a)
+ ##self.assertEquals(cc.lookup(['md5-crypt']), None)
+ ##self.assertEquals(cc.lookup(['unsalted', 'salted', 'md5-crypt']), b)
#TODO: lookup required=True
def test_51_identify(self):
"test CryptContext.identify"
cc = CryptContext([UnsaltedAlg, SaltedAlg, SampleAlg])
- a, b, c = cc
+ a, b, c = cc._handlers
for crypt in (a, b, c):
h = crypt.encrypt("test")
@@ -388,7 +385,7 @@ class CryptContextTest(TestCase):
def test_52_encrypt_and_verify(self):
"test CryptContext.encrypt & verify"
cc = CryptContext([UnsaltedAlg, SaltedAlg, SampleAlg])
- a, b, c = cc
+ a, b, c = cc._handlers
#check encrypt/id/verify pass for all algs
for crypt in (a, b, c):
@@ -408,7 +405,7 @@ class CryptContextTest(TestCase):
def test_53_encrypt_salting(self):
"test CryptContext.encrypt salting options"
cc = CryptContext([UnsaltedAlg, SaltedAlg, SampleAlg])
- a, b, c = cc
+ a, b, c = cc._handlers
self.assert_(c.has_salt)
h = cc.encrypt("test")
@@ -426,7 +423,7 @@ class CryptContextTest(TestCase):
"test CryptContext.verify allows hash=None"
cc = CryptContext([UnsaltedAlg, SaltedAlg, SampleAlg])
self.assertEquals(cc.verify('xxx', None), False)
- for crypt in cc:
+ for crypt in cc._handlers:
self.assertEquals(cc.verify('xxx', None, alg=crypt.name), False)
#XXX: haven't decided if this should be part of protocol
diff --git a/passlib/tests/test_hash_bcrypt.py b/passlib/tests/test_bcrypt.py
index 5862fb7..8f62846 100755
--- a/passlib/tests/test_hash_bcrypt.py
+++ b/passlib/tests/test_bcrypt.py
@@ -26,9 +26,9 @@ except ImportError:
pybcrypt = None
#pkg
from passlib.tests.utils import TestCase, enable_suite
-from passlib.hash import _slow_bcrypt as slow_bcrypt
-from passlib.tests.test_hash_base import _CryptTestCase as CryptTestCase
-import passlib.hash.bcrypt as mod
+from passlib import _slow_bcrypt as slow_bcrypt
+from passlib.tests.test_base import _CryptTestCase as CryptTestCase
+import passlib.bcrypt as mod
#=========================================================
#test slow_bcrypt backend
diff --git a/passlib/tests/test_hash_frontend.py b/passlib/tests/test_frontend.py
index 3887c7b..60e6095 100644
--- a/passlib/tests/test_hash_frontend.py
+++ b/passlib/tests/test_frontend.py
@@ -9,7 +9,7 @@ import warnings
from logging import getLogger
#site
#pkg
-from passlib import hash as pwhash
+import passlib as mod
from passlib.tests.utils import TestCase
#module
log = getLogger(__name__)
@@ -17,12 +17,21 @@ log = getLogger(__name__)
#=========================================================
#pull crypt tests
#=========================================================
-#this test suite uses info stored in the specific hash algs' test suites,
-#so we have to import them here.
-from passlib.tests.test_hash_sha_crypt import Sha256CryptTest, Sha512CryptTest
-from passlib.tests.test_hash_unix_crypt import UnixCryptTest
-from passlib.tests.test_hash_bcrypt import BCryptTest
-from passlib.tests.test_hash_md5_crypt import Md5CryptTest
+def get_crypt_cases():
+
+ #this test suite uses info stored in the specific hash algs' test suites,
+ #so we have to import them here.
+ from passlib.tests.test_sha_crypt import Sha256CryptTest, Sha512CryptTest
+ from passlib.tests.test_unix_crypt import UnixCryptTest
+ from passlib.tests.test_bcrypt import BCryptTest
+ from passlib.tests.test_md5_crypt import Md5CryptTest
+
+ crypt_cases = [ UnixCryptTest, Md5CryptTest, Sha256CryptTest]
+ if BCryptTest:
+ crypt_cases.append(BCryptTest)
+ crypt_cases.extend([ Sha512CryptTest ])
+
+ return crypt_cases
#=========================================================
#quick access functions
@@ -30,14 +39,11 @@ from passlib.tests.test_hash_md5_crypt import Md5CryptTest
class QuickAccessTest(TestCase):
"test quick access functions"
- crypt_cases = [ UnixCryptTest, Md5CryptTest, Sha256CryptTest]
- if BCryptTest:
- crypt_cases.append(BCryptTest)
- crypt_cases.extend([ Sha512CryptTest ])
+ crypt_cases = get_crypt_cases()
def test_00_identify(self):
"test pwhash.identify()"
- identify = pwhash.identify
+ identify = mod.identify
for cc in self.crypt_cases:
name = cc.alg.name
for _, hash in cc.positive_knowns:
@@ -51,7 +57,7 @@ class QuickAccessTest(TestCase):
def test_01_verify(self):
"test pwhash.verify()"
- verify = pwhash.verify
+ verify = mod.verify
for cc in self.crypt_cases:
name = cc.alg.name
for secret, hash in cc.positive_knowns[:3]:
@@ -66,9 +72,9 @@ class QuickAccessTest(TestCase):
def test_02_encrypt(self):
"test pwhash.encrypt()"
- identify = pwhash.identify
- verify = pwhash.verify
- encrypt = pwhash.encrypt
+ identify = mod.identify
+ verify = mod.verify
+ encrypt = mod.encrypt
for cc in self.crypt_cases:
alg = cc.alg.name
s = 'test'
@@ -81,14 +87,14 @@ class QuickAccessTest(TestCase):
def test_04_default_context(self):
"test pwhash.default_context contents"
- dc = pwhash.default_context
+ dc = mod.default_context
for case in self.crypt_cases:
- self.assert_(case.alg.name in dc)
+ self.assert_(dc.lookup(case.alg.name) is case.alg)
- last = 'sha-512-crypt'
- self.assertEqual(dc.keys()[-1], last)
+ last = 'sha512-crypt'
+ self.assertEqual(dc.lookup().name, last)
h = dc.encrypt("test")
- self.assertEqual(dc.identify(h), last)
+ self.assertEqual(dc.identify(h).name, last)
self.assertEqual(dc.verify('test', h, alg=last), True)
#=========================================================
diff --git a/passlib/tests/test_hash_md5_crypt.py b/passlib/tests/test_md5_crypt.py
index 01a6c85..3197f7e 100644
--- a/passlib/tests/test_hash_md5_crypt.py
+++ b/passlib/tests/test_md5_crypt.py
@@ -9,10 +9,9 @@ import warnings
from logging import getLogger
#site
#pkg
-from passlib import hash as pwhash
from passlib.tests.utils import TestCase, enable_suite
-from passlib.tests.test_hash_base import _CryptTestCase as CryptTestCase
-import passlib.hash.md5_crypt as mod
+from passlib.tests.test_base import _CryptTestCase as CryptTestCase
+import passlib.md5_crypt as mod
#module
log = getLogger(__name__)
diff --git a/passlib/tests/test_hash_mysql.py b/passlib/tests/test_mysql.py
index c3ce9ef..2842b36 100644
--- a/passlib/tests/test_hash_mysql.py
+++ b/passlib/tests/test_mysql.py
@@ -9,10 +9,9 @@ import warnings
from logging import getLogger
#site
#pkg
-from passlib import hash as pwhash
from passlib.tests.utils import TestCase, enable_suite
-from passlib.tests.test_hash_base import _CryptTestCase as CryptTestCase
-import passlib.hash.mysql as mod
+from passlib.tests.test_base import _CryptTestCase as CryptTestCase
+import passlib.mysql as mod
#module
log = getLogger(__name__)
diff --git a/passlib/tests/test_hash_pbkdf2.py b/passlib/tests/test_pbkdf2.py
index e1807d4..92f2f7c 100644
--- a/passlib/tests/test_hash_pbkdf2.py
+++ b/passlib/tests/test_pbkdf2.py
@@ -1,4 +1,4 @@
-"""tests for passlib.hash.pbkdf2"""
+"""tests for passlib.pbkdf2"""
#=========================================================
#imports
#=========================================================
@@ -11,8 +11,8 @@ from logging import getLogger
#site
#pkg
from passlib.tests.utils import TestCase, enable_suite
-import passlib.hash.pbkdf2 as mod
-from passlib.tests.test_hash_base import _CryptTestCase as CryptTestCase
+import passlib.pbkdf2 as mod
+from passlib.tests.test_base import _CryptTestCase as CryptTestCase
#module
log = getLogger(__name__)
diff --git a/passlib/tests/test_hash_postgres.py b/passlib/tests/test_postgres.py
index d3290c9..dab23a5 100644
--- a/passlib/tests/test_hash_postgres.py
+++ b/passlib/tests/test_postgres.py
@@ -9,10 +9,9 @@ import warnings
from logging import getLogger
#site
#pkg
-from passlib import hash as pwhash
from passlib.tests.utils import TestCase, enable_suite
-from passlib.tests.test_hash_base import _CryptTestCase as CryptTestCase
-import passlib.hash.postgres as mod
+from passlib.tests.test_base import _CryptTestCase as CryptTestCase
+import passlib.postgres as mod
#module
log = getLogger(__name__)
diff --git a/passlib/tests/test_hash_sha_crypt.py b/passlib/tests/test_sha_crypt.py
index 8a0eb54..68cc635 100644
--- a/passlib/tests/test_hash_sha_crypt.py
+++ b/passlib/tests/test_sha_crypt.py
@@ -9,10 +9,9 @@ import warnings
from logging import getLogger
#site
#pkg
-from passlib import hash as pwhash
from passlib.tests.utils import TestCase, enable_suite
-from passlib.tests.test_hash_base import _CryptTestCase as CryptTestCase
-import passlib.hash.sha_crypt as mod
+from passlib.tests.test_base import _CryptTestCase as CryptTestCase
+import passlib.sha_crypt as mod
#module
log = getLogger(__name__)
@@ -58,6 +57,8 @@ class Sha512BackendTest(TestCase):
"hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." ),
]
def test512(self):
+ "verify sha512 passes specification test vectors"
+
crypt = mod.Sha512Crypt
for hash, secret, result in self.cases512:
diff --git a/passlib/tests/test_hash_unix_crypt.py b/passlib/tests/test_unix_crypt.py
index 868aa1f..5ffab35 100644
--- a/passlib/tests/test_hash_unix_crypt.py
+++ b/passlib/tests/test_unix_crypt.py
@@ -10,9 +10,9 @@ from logging import getLogger
#site
#pkg
from passlib.tests.utils import TestCase, enable_suite
-from passlib.hash._slow_unix_crypt import crypt as builtin_crypt
-import passlib.hash.unix_crypt as mod
-from passlib.tests.test_hash_base import _CryptTestCase as CryptTestCase
+from passlib._slow_unix_crypt import crypt as builtin_crypt
+import passlib.unix_crypt as mod
+from passlib.tests.test_base import _CryptTestCase as CryptTestCase
#module
log = getLogger(__name__)
@@ -95,7 +95,7 @@ class UnixCryptBackendTest(TestCase):
self.assertRaises(ValueError, crypt, "fooey","")
#NOTE: stdlib crypt's behavior is rather bizarre in this case
- # (see wrapper in passlib.hash.unix_crypt).
+ # (see wrapper in passlib.unix_crypt).
# passlib wraps stdlib crypt so it raises ValueError
self.assertRaises(ValueError, crypt, "fooey","f")
diff --git a/passlib/hash/unix_crypt.py b/passlib/unix_crypt.py
index 062d766..c2d8c51 100644
--- a/passlib/hash/unix_crypt.py
+++ b/passlib/unix_crypt.py
@@ -1,4 +1,4 @@
-"""passlib.hash - implementation of various password hashing functions"""
+"""passlib - implementation of various password hashing functions"""
#=========================================================
#imports
#=========================================================
@@ -12,7 +12,7 @@ import time
import os
#site
#pkg
-from passlib.hash.base import CryptAlgorithm, register_crypt_algorithm
+from passlib.base import CryptAlgorithm, register_crypt_algorithm
from passlib.util import classproperty, abstractmethod, is_seq, srandom, h64_gensalt, h64_validate
#local
__all__ = [
diff --git a/passlib/util.py b/passlib/util.py
index ee0ebf0..469bef3 100644
--- a/passlib/util.py
+++ b/passlib/util.py
@@ -231,7 +231,7 @@ def h64_validate(value):
"helper to validate salt strings"
return all(c in H64_CHARS for c in value)
-def h64_encode_3_offsets(cls, buffer, o1, o2, o3):
+def h64_encode_3_offsets(buffer, o1, o2, o3):
"do hash64 encode of three bytes at specified offsets in buffer; returns 4 chars"
#how 4 char output corresponds to 3 byte input:
#
@@ -252,7 +252,7 @@ def h64_encode_3_offsets(cls, buffer, o1, o2, o3):
H64_CHARS[((v3&0x03)<<4) + (v2>>4)] + \
H64_CHARS[v3>>2]
-def h64_encode_2_offsets(cls, buffer, o1, o2):
+def h64_encode_2_offsets(buffer, o1, o2):
"do hash64 encode of two bytes at specified offsets in buffer; 2 missing msg set null; returns 3 chars"
v1 = ord(buffer[o1])
v2 = ord(buffer[o2])
@@ -260,7 +260,7 @@ def h64_encode_2_offsets(cls, buffer, o1, o2):
H64_CHARS[((v2&0x0F)<<2) + (v1>>6)] + \
H64_CHARS[(v2>>4)]
-def h64_encode_1_offset(cls, buffer, o1):
+def h64_encode_1_offset(buffer, o1):
"do hash64 encode of single byte at specified offset in buffer; 4 missing msb set null; returns 2 chars"
v1 = ord(buffer[o1])
return H64_CHARS[v1&0x3F] + H64_CHARS[v1>>6]