summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/install.rst18
-rw-r--r--docs/lib/passlib.hash.hex_digests.rst9
-rw-r--r--passlib/context.py24
-rw-r--r--passlib/registry.py2
-rw-r--r--passlib/utils/pbkdf2.py38
5 files changed, 52 insertions, 39 deletions
diff --git a/docs/install.rst b/docs/install.rst
index fe2c048..28a9172 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -6,7 +6,7 @@ Supported Platforms
===================
Passlib requires Python 2 (>= 2.5) or Python 3.
It should work with the following Python implementations:
-
+
* CPython 2 -- 2.5 or newer.
* CPython 3 -- all versions.
* PyPy -- 1.5 or newer.
@@ -14,12 +14,12 @@ It should work with the following Python implementations:
Passlib should work with all operating systems,
as it contains builtin fallbacks
-for almost all OS-dependant features.
+for almost all OS-dependant features.
Optional Libraries
==================
* `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_ or
- `bcryptor <https://bitbucket.org/ares/bcryptor/overview>`_
+ `bcryptor <https://bitbucket.org/ares/bcryptor/overview>`_
If either of these packages are installed, they will be used to provide
support for the BCrypt hash algorithm.
@@ -32,7 +32,7 @@ Optional Libraries
If installed, M2Crypto will be used to accelerate some internal
functions used by PBKDF2-based hashes, but it is not required
even in that case.
-
+
Installation Instructions
=========================
To download and install using :command:`easy_install`::
@@ -42,16 +42,16 @@ To download and install using :command:`easy_install`::
To download and install using :command:`pip`::
pip install passlib
-
+
To install from a source directory using :command:`setup.py`::
- python setup.py install
+ python setup.py install
.. note::
-
+
Passlib's source ships as Python 2 code,
and the setup script invokes the :command:`2to3` tool + a preprocessor
- to translate the source to Python 3 code at install time.
+ to translate the source to Python 3 code at install time.
Aside from this internal detail,
installation under Python 3
should be identical to that of Python 2.
@@ -76,6 +76,8 @@ Once PassLib and Nose have been installed, the tests may be run from the source
PASSLIB_TESTS="all" nosetests -v passlib/tests --with-coverage \
--cover-package=passlib --cover-html --cover-html-dir build/coverage
+(There will be a large proportion of skipped tests, this is normal).
+
Documentation
=============
The latest copy of this documentation should always be available
diff --git a/docs/lib/passlib.hash.hex_digests.rst b/docs/lib/passlib.hash.hex_digests.rst
index 9bc3653..8b3100f 100644
--- a/docs/lib/passlib.hash.hex_digests.rst
+++ b/docs/lib/passlib.hash.hex_digests.rst
@@ -11,6 +11,15 @@ and should not be used in new applications. However, for the sake
of backwards compatibility when converting existing applications,
PassLib provides wrappers for few of the common hashes.
+.. warning::
+
+ To reiterate the above:
+ Using a single round of any cryptographic hash
+ (especially without a salt) is so insecure
+ that it's barely better than plaintext.
+ Do not use these schemes in new applications.
+
+
Usage
=====
These classes all wrap the underlying hashlib implementations,
diff --git a/passlib/context.py b/passlib/context.py
index 77ea10c..5426042 100644
--- a/passlib/context.py
+++ b/passlib/context.py
@@ -59,7 +59,7 @@ def _parse_policy_key(key):
def _parse_policy_value(cat, name, opt, value):
"helper to parse policy values"
- #FIXME: kinda primitive :|
+ #FIXME: kinda primitive to parse things this way :|
if name == "context":
if opt == "schemes" or opt == "deprecated":
if isinstance(value, str):
@@ -78,10 +78,10 @@ def parse_policy_items(source):
"helper to parse CryptPolicy options"
# py2k #
if hasattr(source, "iteritems"):
- source = source.iteritems()
+ source = source.iteritems()
# py3k #
#if hasattr(source, "items"):
- # source = source.items()
+ # source = source.items()
# end py3k #
for key, value in source:
cat, name, opt = _parse_policy_key(key)
@@ -180,7 +180,7 @@ class CryptPolicy(object):
"""
#NOTE: we want config parser object to have native strings as keys.
# so we parse as bytes under py2, and unicode under py3.
- #
+ #
# encoding issues are handled under py2 via to_bytes(),
# which ensures everything is utf-8 internally.
@@ -194,12 +194,12 @@ class CryptPolicy(object):
with open(path, "rb") as stream:
source = stream.read()
source = source.decode(encoding).encode("utf-8")
- return cls._from_stream(StringIO(source), section, path)
+ return cls._from_stream(StringIO(source), section, path)
# Py3k #
#with open(path, "r", encoding=encoding) as stream:
# return cls._from_stream(stream, section, path)
# end Py3k #
-
+
@classmethod
def from_string(cls, source, section="passlib", encoding="utf-8"):
"""create new policy from specified section of an ini-formatted string.
@@ -214,7 +214,7 @@ class CryptPolicy(object):
# so we parse as bytes under py2, and unicode under py3.
# to handle encoding issues under py2, we use
# "to_bytes()" to transcode to utf-8 as needed.
-
+
# Py2k #
source = to_bytes(source, "utf-8", source_encoding=encoding, errname="source")
# Py3k #
@@ -240,20 +240,20 @@ class CryptPolicy(object):
raise
#support for deprecated 1.4 behavior, will be removed in 1.6
if filename:
- warn("from_path(): the file %r contains an unescaped '%%', this will be fatal in passlib 1.6" % (path,), stacklevel=3)
+ warn("from_path(): the file %r contains an unescaped '%%', this will be fatal in passlib 1.6" % (path,), stacklevel=3)
else:
warn("from_string(): the provided string contains an unescaped '%', this will be fatal in passlib 1.6", stacklevel=3)
p = ConfigParser()
stream.seek(pos)
p.readfp(stream)
items = p.items(section)
-
+
# py3k #
#items = p.items(section)
# end py3k #
-
+
return cls(**dict(items))
-
+
@classmethod
def from_source(cls, source):
"""create new policy from input.
@@ -674,7 +674,7 @@ class CryptPolicy(object):
self._write_to_parser(p, section)
p.write(stream)
- def to_string(self, section="passlib", encoding=None):
+ def to_string(self, section="passlib", encoding=None):
"render to INI string; inverse of from_string() constructor"
buf = StringIO()
self.to_file(buf, section)
diff --git a/passlib/registry.py b/passlib/registry.py
index 06b9657..f319840 100644
--- a/passlib/registry.py
+++ b/passlib/registry.py
@@ -159,7 +159,7 @@ def register_crypt_handler_path(name, path):
called :samp:`{name}`, or the path may contain a colon,
specifying the module and module attribute to use.
for example, the following would cause ``get_handler("myhash")`` to look
- for a class named ``myhash`` within the ``myapp.helpers`` module::
+ for a class named ``myhash`` within the ``myapp.helpers`` module::
>>> from passlib.registry import registry_crypt_handler_path
>>> registry_crypt_handler_path("myhash", "myapp.helpers")
diff --git a/passlib/utils/pbkdf2.py b/passlib/utils/pbkdf2.py
index aa5ea5b..29477c1 100644
--- a/passlib/utils/pbkdf2.py
+++ b/passlib/utils/pbkdf2.py
@@ -95,33 +95,33 @@ def _clear_prf_cache():
def get_prf(name):
"""lookup pseudo-random family (prf) by name.
-
+
:arg name:
this must be the name of a recognized prf.
currently this only recognizes names with the format
:samp:`hmac-{digest}`, where :samp:`{digest}`
is the name of a hash function such as
``md5``, ``sha256``, etc.
-
+
this can also be a callable with the signature
``prf(secret, message) -> digest``,
in which case it will be returned unchanged.
-
+
:raises ValueError: if the name is not known
:raises TypeError: if the name is not a callable or string
-
+
:returns:
a tuple of :samp:`({func}, {digest_size})`.
-
+
* :samp:`{func}` is a function implementing
the specified prf, and has the signature
``func(secret, message) -> digest``.
-
+
* :samp:`{digest_size}` is an integer indicating
the number of bytes the function returns.
-
+
usage example::
-
+
>>> from passlib.utils.pbkdf2 import get_prf
>>> hmac_sha256, dsize = get_prf("hmac-sha256")
>>> hmac_sha256
@@ -131,7 +131,7 @@ def get_prf(name):
>>> digest = hmac_sha256('password', 'message')
this function will attempt to return the fastest implementation
- it can find; if M2Crypto is present, and supports the specified prf,
+ it can find; if M2Crypto is present, and supports the specified prf,
:func:`M2Crypto.EVP.hmac` will be used behind the scenes.
"""
global _prf_cache
@@ -167,14 +167,16 @@ def pbkdf1(secret, salt, rounds, keylen, hash="sha1"):
* a callable with the prototype ``hash(message) -> raw digest``
* a string matching one of the hashes recognized by hashlib
-
+
:returns:
raw bytes of generated key
-
- This algorithm is deprecated, new code should use PBKDF2.
- Among other reasons, ``keylen`` cannot be larger
- than the digest size of the specified hash.
-
+
+ .. note::
+
+ This algorithm is deprecated, new code should use PBKDF2.
+ Among other reasons, ``keylen`` cannot be larger
+ than the digest size of the specified hash.
+
"""
#prepare secret & salt
if not isinstance(secret, bytes):
@@ -213,7 +215,7 @@ def pbkdf1(secret, salt, rounds, keylen, hash="sha1"):
block = hf(block).digest()
r += 1
return block[:keylen]
-
+
#=================================================================================
#pbkdf2
#=================================================================================
@@ -232,7 +234,7 @@ def pbkdf2(secret, salt, rounds, keylen, prf="hmac-sha1"):
this can be any string or callable accepted by :func:`get_prf`.
this defaults to ``hmac-sha1`` (the only prf explicitly listed in
the PBKDF2 specification)
-
+
:returns:
raw bytes of generated key
"""
@@ -253,7 +255,7 @@ def pbkdf2(secret, salt, rounds, keylen, prf="hmac-sha1"):
#NOTE: doing check here, because M2crypto won't take longs (which this is, under 32bit)
if keylen > MAX_HMAC_SHA1_KEYLEN:
raise ValueError("key length too long")
-
+
#NOTE: M2crypto reliably segfaults for me if given keylengths
# larger than 40 (crashes at 41 on one system, 61 on another).
# so just avoiding it for longer calls.