summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2011-01-31 23:34:37 +0000
committerEli Collins <elic@assurancetechnologies.com>2011-01-31 23:34:37 +0000
commit0eafd59fcee89cf4769add43c057a11e62c49a3a (patch)
tree19b476c6317f76ce39140900d1d671440aef34ae
parent8903ccd8ecf8b26cd5e80466eecfdd8df140482b (diff)
downloadpasslib-0eafd59fcee89cf4769add43c057a11e62c49a3a.tar.gz
updated docs
-rw-r--r--docs/conf.py6
-rw-r--r--docs/contents.rst9
-rw-r--r--docs/copyright.rst29
-rw-r--r--docs/crypt_handler_api.rst3
-rw-r--r--docs/history.rst11
-rw-r--r--docs/index.rst6
-rw-r--r--docs/install.rst28
-rw-r--r--docs/lib/_scratch1.rst (renamed from docs/lib/passlib.hash/algorithms.rst)0
-rw-r--r--docs/lib/_scratch2.rst (renamed from docs/lib/passlib.hash/implementation.rst)0
-rw-r--r--docs/lib/passlib.base.rst (renamed from docs/lib/passlib.hash/contexts.rst)0
-rw-r--r--docs/lib/passlib.gen.rst14
-rw-r--r--docs/lib/passlib.hash.apr_md5_crypt.rst24
-rw-r--r--docs/lib/passlib.hash.bcrypt.rst10
-rw-r--r--docs/lib/passlib.hash.des_crypt.rst10
-rw-r--r--docs/lib/passlib.hash.ext_des_crypt.rst10
-rw-r--r--docs/lib/passlib.hash.md5_crypt.rst10
-rw-r--r--docs/lib/passlib.hash.myql_323.rst10
-rw-r--r--docs/lib/passlib.hash.mysql_41.rst10
-rw-r--r--docs/lib/passlib.hash.postgres_md5.rst33
-rw-r--r--docs/lib/passlib.hash.rst92
-rw-r--r--docs/lib/passlib.hash.sha256_crypt.rst10
-rw-r--r--docs/lib/passlib.hash.sha512_crypt.rst16
-rw-r--r--docs/lib/passlib.hash.sun_md5_crypt.rst10
-rw-r--r--docs/lib/passlib.hash/utils.rst19
-rw-r--r--docs/lib/passlib.unix.rst30
-rw-r--r--docs/lib/passlib.utils.des.rst17
-rw-r--r--docs/lib/passlib.utils.h64.rst42
-rw-r--r--docs/lib/passlib.utils.md4.rst20
-rw-r--r--docs/lib/passlib.utils.pbkdf2.rst15
-rw-r--r--docs/lib/passlib.utils.rst79
-rw-r--r--docs/notes.txt3
-rw-r--r--docs/overview.rst20
-rw-r--r--docs/quickstart.rst (renamed from docs/lib/passlib.hash/quickstart.rst)0
-rw-r--r--passlib/base.py10
-rw-r--r--passlib/hash/apr_md5_crypt.py13
-rw-r--r--passlib/hash/postgres_md5.py24
-rw-r--r--passlib/utils/__init__.py64
-rw-r--r--passlib/utils/des.py14
-rw-r--r--passlib/utils/h64.py61
-rw-r--r--passlib/utils/handlers.py8
-rw-r--r--passlib/utils/md4.py23
41 files changed, 547 insertions, 266 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 6bf186e..206a63a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -38,7 +38,7 @@ import astdoc
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.todo',
-
+
'astdoc.ext.index_styles', #adds extra ids & classes to index html, for additional styling
'astdoc.ext.relbar_toc', #inserts toc into right hand nav bar (ala old style python docs)
'astdoc.ext.nested_sections', #handles ReST markup within function/class docstrings
@@ -59,7 +59,7 @@ index_doc = 'index'
# General information about the project.
project = u'PassLib'
-copyright = u'2008-2010, Assurance Technologies, LLC'
+copyright = u'2008-2011, Assurance Technologies, LLC'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -109,7 +109,7 @@ pygments_style = 'sphinx'
modindex_common_prefix = [ "passlib." ]
# -- Options for all output ---------------------------------------------------
-todo_include_todos = True
+todo_include_todos = "todos" in os.environ.get("PASSLIB_DOCS","")
keep_warnings = True
# -- Options for HTML output ---------------------------------------------------
diff --git a/docs/contents.rst b/docs/contents.rst
index dd4ceb4..5398288 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -8,10 +8,11 @@ Table Of Contents
install
overview
- lib/passlib
- lib/passlib
- lib/passlib.gen
- lib/passlib.util
+ lib/passlib.hash
+ lib/passlib.unix
+ lib/passlib.utils
+
+ crypt_handler_api
history
copyright
diff --git a/docs/copyright.rst b/docs/copyright.rst
index fc2c6ac..354574c 100644
--- a/docs/copyright.rst
+++ b/docs/copyright.rst
@@ -4,7 +4,7 @@ Copyrights & Licenses
Copyright
=========
-The PassLib library is (c) 2008-2010 `Assurance Technologies, LLC <http://www.assurancetechnologies.com>`_,
+The PassLib library is (c) 2008-2011 `Assurance Technologies, LLC <http://www.assurancetechnologies.com>`_,
excepting any code noted below as taken from :ref:`third party sources <third-party-software>`.
Such portions are copyright their respective owners.
@@ -16,7 +16,7 @@ This library is released under the BSD license; we hope you find it useful.
The PassLib Python Library
- Copyright (c) 2008-2010 Assurance Technologies, LLC
+ Copyright (c) 2008-2011 Assurance Technologies, LLC
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -39,21 +39,14 @@ own licenses (all of which, it should be noted, are BSD-compatible).
The following is a list of these sources, their owners, licenses, and the parts
of PassLib derived from them.
-GPW
----
-The class :class:`passlib.gen.GpwGenerator`
-is a python implementation of Tom Van Vleck's phonetic
-password generation algorithm `GPW <http://www.multicians.org/thvv/gpw.html>`_.
-It's released under informally worded BSD-compatible terms.
-
jBcrypt
-------
`jBCrypt <http://www.mindrot.org/projects/jBCrypt/>`_ is a pure-java
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.BCrypt`
+:mod:`passlib.utils._slow_bcrypt` is a python translation of this code,
+which is used as a fallback backend for :mod:`passlib.hash.bCrypt`
when the external python library `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_
is not installed.
@@ -75,10 +68,10 @@ This is the license and copyright for jBCrypt::
MD5-Crypt
---------
-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::
+The fallback pure-python implementation contained in :mod:`passlib.hash.md5_crypt`
+was derived from the
+`FreeBSD md5-crypt <http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libcrypt/crypt.c?rev=1.2>`_,
+implementation which was released under the following license::
"THE BEER-WARE LICENSE" (Revision 42):
<phk@login.dknet.dk> wrote this file. As long as you retain this notice you
@@ -92,9 +85,9 @@ is a pure-java implementation of the historic unix-crypt password hash algorithm
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.UnixCrypt`
-for platforms where stdlib's :mod:`crypt` is not available.
+The DES utility functions in :mod:`passlib.utils.des` are a descendant of
+this code, after being translated into python. (These are used for des-crypt,
+ext-des-crypt, and nthash support).
This is the license and copyright for UnixCrypt.java::
diff --git a/docs/crypt_handler_api.rst b/docs/crypt_handler_api.rst
index 500b0eb..e6192f5 100644
--- a/docs/crypt_handler_api.rst
+++ b/docs/crypt_handler_api.rst
@@ -1,3 +1,5 @@
+.. _crypt-handler-api:
+
======================
api for crypt handlers
======================
@@ -163,4 +165,3 @@ the following attributes are usually exposed:
The maximum number of rounds the scheme allows.
Specifying values above this will generally result
in a warning, and ``max_rounds`` will be used instead.
-
diff --git a/docs/history.rst b/docs/history.rst
index 9a6e9bd..615574b 100644
--- a/docs/history.rst
+++ b/docs/history.rst
@@ -2,15 +2,18 @@
Release History
===============
-??? -- version 1.1
+2011-01-10 -- version 1.0
* first public release
- * documentation added
+ * bugfixes
+ * more documentation
-2011-01-05 -- version 1.0
+2011-01-05 -- version 0.8
* various code cleanups preparing for public release
+ * ext-des-crypt, apr-md5-crypt, and other lesser known schemes added.
+ * documentation added
2009-03-10 -- version 0.7
- * added password generation helpers
+ * postgres and mysql hash schemes added.
2008-10-02 -- version 0.6
* CryptContext & CryptHandler framework
diff --git a/docs/index.rst b/docs/index.rst
index 821ee65..8ffcbc4 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -4,9 +4,9 @@ PassLib |release| documentation
Introduction
============
-Welcome to the documentation for PassLib.
-
-PassLib is a
+Passlib is a collection of routines for managing password hashes
+as found in unix /etc/shadow files, as returned by stdlib `crypt()`,
+as stored in mysql and postgres, and various other contexts.
A quick sample of some of the more frequently used modules:
diff --git a/docs/install.rst b/docs/install.rst
index 1b29858..f6ba0c6 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -4,22 +4,26 @@ Installation
Requirements
============
-PassLib tries to use pure-python implementations of things whereever possible,
-and have as few dependancies as possible. The current set of requirements is:
+PassLib currently has no external depedancies besides Python itself:
* Python 2.5 or better is required.
* PassLib has not been tested with Python 2.4 or earlier,
and no guarantees are made about whether PassLib will work with them.
- * Python 3.x has **not** been assessed for compatibility.
- It probably won't work just yet.
+ * Python 3.x is **not** yet supported, work is ongoing (particularly, unicode issues).
-The following libraries will be used if present, but they are not required:
+The following libraries are not required, but will be used if found:
* 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.BCrypt`).
+ (see :mod:`passlib.hash.bcrypt`).
+ *This is strongly recommended, as the builtin implementation is VERY slow*.
+
+ * stdlib ``crypt.crypt()`` will be used if present, and if the underlying
+ OS supports the specific scheme in question. OS support is autodetected
+ from the following schemes: des-crypt, md5-crypt, bcrypt, sha256-crypt,
+ and sha512-crypt.
Installing
==========
@@ -31,20 +35,20 @@ PassLib is pure python, there is nothing to compile or configure.
Testing
=======
PassLib contains a number of unittests (sadly, coverage is not yet complete).
-all of which are contained within the :mod:`passlib.tests` package,
-and are designed to be run using the `nose <http://somethingaboutorange.com/mrl/projects/nose>`_ unit testing library.
+All unit tests are contained within the :mod:`passlib.tests` package,
+and are designed to be run using the `Nose <http://somethingaboutorange.com/mrl/projects/nose>`_ unit testing library.
Once PassLib and nose have been installed, you may run the following commands::
#to run the basic passlib test suite:
- nosetests passlib/tests
+ nosetests -v passlib.tests
- #to run the extended passlib test suite, including some longer running tests:
+ #to test all passlib backends, including inactive ones:
export PASSLIB_TESTS=all
- nosetests passlib/tests
+ nosetests passlib.tests
Documentation
=============
-The latest copy of this documentation should always be available
+The latest copy of this documentation should always be available
at the `PassLib homepage <http://www.assurancetechnologies.com/software/passlib>`_.
If you wish to generate your own copy of the documentation,
diff --git a/docs/lib/passlib.hash/algorithms.rst b/docs/lib/_scratch1.rst
index 4c00293..4c00293 100644
--- a/docs/lib/passlib.hash/algorithms.rst
+++ b/docs/lib/_scratch1.rst
diff --git a/docs/lib/passlib.hash/implementation.rst b/docs/lib/_scratch2.rst
index d80ac56..d80ac56 100644
--- a/docs/lib/passlib.hash/implementation.rst
+++ b/docs/lib/_scratch2.rst
diff --git a/docs/lib/passlib.hash/contexts.rst b/docs/lib/passlib.base.rst
index aa463f9..aa463f9 100644
--- a/docs/lib/passlib.hash/contexts.rst
+++ b/docs/lib/passlib.base.rst
diff --git a/docs/lib/passlib.gen.rst b/docs/lib/passlib.gen.rst
deleted file mode 100644
index b8778e9..0000000
--- a/docs/lib/passlib.gen.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-================================================
-:mod:`passlib.gen` -- Password Generation
-================================================
-
-.. module:: passlib.gen
- :synopsis: password generation algorithms
-
-The following single function allows
-easy password generation in a number of styles:
-
-.. autofunction:: generate_secret
-
-.. todo::
- document internal classes
diff --git a/docs/lib/passlib.hash.apr_md5_crypt.rst b/docs/lib/passlib.hash.apr_md5_crypt.rst
new file mode 100644
index 0000000..272c08d
--- /dev/null
+++ b/docs/lib/passlib.hash.apr_md5_crypt.rst
@@ -0,0 +1,24 @@
+=============================================================
+:mod:`passlib.hash.apr_md5_crypt` - Apache MD5-Crypt Variant
+=============================================================
+
+.. module:: passlib.hash.apr_md5_crypt
+ :synopsis: Apache MD5 Crypt
+
+Stats: 96 bit checksum, 48 bit salt, :ref:`modular-crypt-format` compatible.
+
+This format is a variation of :mod:`~passlib.hash.md5_crypt`,
+primarily used by the Apache webserver in ``htpasswd`` files.
+
+This format is identical to md5-crypt, except for two things:
+it uses ``$apr1$`` as a prefix where md5-crypt uses ``$1$``,
+and inserts ``$apr1$`` where md5-crypt inserts ``$1$`` into
+it's internal hash calculation. Thus, this algorithm is just
+as strong as md5-crypt, but the formats (and their contained checksums)
+are in no way compatible with eachother.
+
+Implementation
+==============
+PassLib contains a builtin pure-python implementation of apr-md5-crypt,
+based of the specification at `http://httpd.apache.org/docs/2.2/misc/password_encryptions.html`,
+but code shared with :mod:`~passlib.hash.md5_crypt`.
diff --git a/docs/lib/passlib.hash.bcrypt.rst b/docs/lib/passlib.hash.bcrypt.rst
new file mode 100644
index 0000000..0b22e07
--- /dev/null
+++ b/docs/lib/passlib.hash.bcrypt.rst
@@ -0,0 +1,10 @@
+==================================================================
+:mod:`passlib.hash.bcrypt` - BCrypt
+==================================================================
+
+.. module:: passlib.hash.bcrypt
+ :synopsis: implementation of blowfish-based BCrypt scheme
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash.des_crypt.rst b/docs/lib/passlib.hash.des_crypt.rst
new file mode 100644
index 0000000..6b7e195
--- /dev/null
+++ b/docs/lib/passlib.hash.des_crypt.rst
@@ -0,0 +1,10 @@
+========================================================
+:mod:`passlib.hash.des_crypt` - Unix (DES) Crypt
+========================================================
+
+.. module:: passlib.hash.des_crypt
+ :synopsis: implementation of original unix-crypt / des-crypt scheme
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash.ext_des_crypt.rst b/docs/lib/passlib.hash.ext_des_crypt.rst
new file mode 100644
index 0000000..35da109
--- /dev/null
+++ b/docs/lib/passlib.hash.ext_des_crypt.rst
@@ -0,0 +1,10 @@
+==================================================================
+:mod:`passlib.hash.ext_des_crypt` - BSDi Extended Unix (DES) Crypt
+==================================================================
+
+.. module:: passlib.hash.ext_des_crypt
+ :synopsis: implementation of BSDi extended unix/des crypt scheme
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash.md5_crypt.rst b/docs/lib/passlib.hash.md5_crypt.rst
new file mode 100644
index 0000000..78fe3f3
--- /dev/null
+++ b/docs/lib/passlib.hash.md5_crypt.rst
@@ -0,0 +1,10 @@
+==================================================================
+:mod:`passlib.hash.md5_crypt` - MD5-Crypt
+==================================================================
+
+.. module:: passlib.hash.md5_crypt
+ :synopsis: implementation of MD5-Crypt scheme
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash.myql_323.rst b/docs/lib/passlib.hash.myql_323.rst
new file mode 100644
index 0000000..6bb1467
--- /dev/null
+++ b/docs/lib/passlib.hash.myql_323.rst
@@ -0,0 +1,10 @@
+==================================================================
+:mod:`passlib.hash.mysql_323` - MySQL 3.2.3 "OLD_PASSWORD" Scheme
+==================================================================
+
+.. module:: passlib.hash.mysql_323
+ :synopsis: MySQL 3.2.3 "OLD_PASSWORD" scheme
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash.mysql_41.rst b/docs/lib/passlib.hash.mysql_41.rst
new file mode 100644
index 0000000..3665ebf
--- /dev/null
+++ b/docs/lib/passlib.hash.mysql_41.rst
@@ -0,0 +1,10 @@
+==================================================================
+:mod:`passlib.hash.mysql_41` - MySQL 4.1 "NEW_PASSWORD" Scheme
+==================================================================
+
+.. module:: passlib.hash.mysql_41
+ :synopsis: MySQL 4.1 "NEW_PASSWORD" scheme
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash.postgres_md5.rst b/docs/lib/passlib.hash.postgres_md5.rst
new file mode 100644
index 0000000..0b75dd5
--- /dev/null
+++ b/docs/lib/passlib.hash.postgres_md5.rst
@@ -0,0 +1,33 @@
+==================================================================
+:mod:`passlib.hash.postgres_md5` - Postgres MD5 password hash
+==================================================================
+
+.. module:: passlib.hash.mysql_md5
+ :synopsis: Postgres MD5 password hash
+
+Stats: 512 bit checksum, username used as salt
+
+This implements the md5-based hash algorithm used by Postgres to store
+passwords in the pg_shadow table.
+
+This algorithm shouldn't be used for any purpose besides Postgres interaction,
+it's a weak unsalted algorithm which could be attacked with a rainbow table
+built against common user names.
+
+.. warning::
+ This algorithm is slightly different from most of the others,
+ in that both encrypt() and verify() require you pass in
+ the name of the user account via the required 'user' keyword,
+ since postgres uses this in place of a salt :(
+
+Usage Example::
+
+ >>> from passlib.hash import postgres_md5 as pm
+ >>> pm.encrypt("mypass", user="postgres")
+ 'md55fba2ea04fd36069d2574ea71c8efe9d'
+ >>> pm.verify("mypass", 'md55fba2ea04fd36069d2574ea71c8efe9d', user="postgres")
+ True
+
+.. todo::
+
+ find references
diff --git a/docs/lib/passlib.hash.rst b/docs/lib/passlib.hash.rst
index 621ed0d..313fa2e 100644
--- a/docs/lib/passlib.hash.rst
+++ b/docs/lib/passlib.hash.rst
@@ -1,44 +1,66 @@
-=============================================
-:mod:`passlib` - Password Hashing
-=============================================
+============================================
+:mod:`passlib.hash` - Password Hash Schemes
+============================================
-.. module:: passlib
- :synopsis: password hashing (unix-crypt, md5-crypt, etc)
+.. module:: passlib.hash
+ :synopsis: package containing handlers for all builtin password hash schemes
Overview
========
-This module handles encrypting and verifying password hashes
-(such as from unix shadow files). This module contains implementations of most
-of the modern password hashing algorithms,
-as well as a complex framework for implementing
-new algorithms, managing hashes generated
-within different contexts with different supported
-algorithms, and other features.
+This package contains handlers for all the password hash schemes built into
+passlib. All modules within this package implement a single scheme,
+and follow the :ref:`crypt-handler-api`. They can be imported
+and used directly, eg::
-The algorithms currently supported by default in BPS:
+ >>> from passlib.hash import md5_crypt
+ >>> hash = md5_crypt.encrypt("password")
- * Unix-Crypt
- * MD5-Crypt
- * BCrypt
- * SHA-Crypt (256 & 512 bit modes)
+As well, any third-party handlers registered with passlib via :func:`register_crypt_handler`
+will be inserted into this package.
- * PostgreSQL & MySQL password hashes
+Note that many applications may find it easier to use a :class:`CryptContext`
+instance, or retreive handlers via :func:`get_crypt_handler`, rather than
+import directly from this module.
-Sections
+Contents
========
-The documentation for the pwhash module is broken into the following sections:
-
-* :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/quickstart
- passlib/contexts
- passlib/algorithms
- passlib/implementation
- passlib/utils
+Passlib contains the following builtin password algorithms:
+
+Standard Unix Schemes
+---------------------
+All these schemes are/were used by various unix flavors to store user passwords.
+Because of this, all these schemes (except des-crypt and ext-des-crypt) follow
+the :ref:`modular crypt format <modular-crypt-format>`.
+
+* :mod:`~passlib.hash.des_crypt` - Legacy DES-based unix crypt() algorithm.
+* :mod:`~passlib.hash.ext_des_crypt` - Legacy BSDi extension of des-crypt which adds more salt and variable rounds.
+* :mod:`~passlib.hash.md5_crypt` - MD5-based descendant of des-crypt.
+* :mod:`~passlib.hash.bcrypt` - Blowfish-based replacement for md5-crypt, used mostly on BSD systems.
+* :mod:`~passlib.hash.sha256_crypt` - SHA-256 based descendant of MD5 crypt, used mostly on Linux systems.
+* :mod:`~passlib.hash.sha512_crypt` - SHA-512 based descendant of MD5 crypt, used mostly on Linux systems.
+
+Non-Standard Unix-Compatible Schemes
+------------------------------------
+While few of these schemes were ever used by unix flavors to store user passwords,
+these are compatible with the :ref:`modular crypt format <modular-crypt-format>`, and can be
+used in contexts which support them in parallel with the others following
+the same format.
+
+* :mod:`~passlib.hash.apr_md5_crypt` - Apache-specific variant of md5-crypt, used in htpasswd files
+
+.. todo::
+
+ These aren't fully implemented / tested yet:
+
+ * :mod:`~passlib.hash.nthash` - modular-crypt-format encoding of legacy NTHASH algorithm
+ * :mod:`~passlib.hash.sun_md5_crypt` - MD5-based crypt descendant used by Solaris 10 (NOT related to md5-crypt above).
+
+Other Schemes
+-------------
+The following schemes are used in very specified contexts,
+and have encoding schemes and other requirements
+not seen outside those specific contexts:
+
+* :mod:`~passlib.hash.mysql_323` - Legacy scheme used by MySQL 3.2.3+ to store user passwords
+* :mod:`~passlib.hash.mysql_41` - Current scheme used by MySQL 4.1+ to store user passwords
+* :mod:`~passlib.hash.postgres_md5` - Current scheme used by PostgreSQL to store user passwords
diff --git a/docs/lib/passlib.hash.sha256_crypt.rst b/docs/lib/passlib.hash.sha256_crypt.rst
new file mode 100644
index 0000000..fbb23b0
--- /dev/null
+++ b/docs/lib/passlib.hash.sha256_crypt.rst
@@ -0,0 +1,10 @@
+==================================================================
+:mod:`passlib.hash.sha256_crypt` - SHA-256 Crypt
+==================================================================
+
+.. module:: passlib.hash.sha526_crypt
+ :synopsis: implementation of SHA-256 Crypt scheme
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash.sha512_crypt.rst b/docs/lib/passlib.hash.sha512_crypt.rst
new file mode 100644
index 0000000..325d963
--- /dev/null
+++ b/docs/lib/passlib.hash.sha512_crypt.rst
@@ -0,0 +1,16 @@
+==================================================================
+:mod:`passlib.hash.sha512_crypt` - SHA-512 Crypt
+==================================================================
+
+.. module:: passlib.hash.sha526_crypt
+ :synopsis: implementation of SHA-512 Crypt scheme
+
+Defined in the same specification, the SHA-512 Crypt scheme is almost identical to SHA-256 Crypt,
+except for the following differences:
+
+* it uses the prefix ``$6$`` where the SHA-256 Crypt uses ``$5$``.
+* it uses SHA-512 as it's internal hash function
+* it's output hash is correspondingly larger.
+
+For details about this module, see :mod:`~passlib.hash.sha256_crypt`,
+it is exactly the same except for the above differences.
diff --git a/docs/lib/passlib.hash.sun_md5_crypt.rst b/docs/lib/passlib.hash.sun_md5_crypt.rst
new file mode 100644
index 0000000..7db3bc9
--- /dev/null
+++ b/docs/lib/passlib.hash.sun_md5_crypt.rst
@@ -0,0 +1,10 @@
+=============================================================
+:mod:`passlib.hash.sun_md5_crypt` - Sun MD5-Crypt
+=============================================================
+
+.. module:: passlib.hash.sun_md5_crypt
+ :synopsis: Sun MD5 Crypt implementation
+
+.. todo::
+
+ write documentation
diff --git a/docs/lib/passlib.hash/utils.rst b/docs/lib/passlib.hash/utils.rst
deleted file mode 100644
index 752e381..0000000
--- a/docs/lib/passlib.hash/utils.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-=============================================
-:mod:`passlib` - Helper Functions
-=============================================
-
-.. currentmodule:: passlib
-
-A couple of utility functions are available,
-mainly useful when writing custom password hash algorithms.
-The ``h64_*`` series of functions all provide
-utilities for encoding & decoding strings
-under the modified base64 system used by most
-of the standard unix hash algorithms.
-
-.. autofunction:: h64_encode
-.. autofunction:: h64_decode
-.. autofunction:: h64_gen_salt
-
-.. autofunction:: is_crypt_context
-.. autofunction:: is_crypt_handler
diff --git a/docs/lib/passlib.unix.rst b/docs/lib/passlib.unix.rst
new file mode 100644
index 0000000..9acf867
--- /dev/null
+++ b/docs/lib/passlib.unix.rst
@@ -0,0 +1,30 @@
+============================================
+:mod:`passlib.unix` - Password Hash Schemes
+============================================
+
+.. module:: passlib.unix
+ :synopsis: helpers for encrypting & verifying passwords on unix systems
+
+.. _modular-crypt-format:
+
+Modular Crypt Format
+====================
+A vast majority of the schemes used on unix systems (and supported by this library)
+follow the "Modular Crypt Format", introduced around the time :mod:`~passlib.hash.md5_crypt` was developed.
+This scheme allows hashes generates by multiple schemes to co-exist within a database,
+by requiring that all hash string begin with a unique prefix ``$identifier$``;
+where ``identifier`` is a short alphanumeric string globally identifying
+hashes generated by that algorithm.
+
+While not part of the specification, most modular crypt -compatible hashes
+were designed to be used by unix systems to store user account passwords
+in ``/etc/passwd`` or ``/etc/shadow``. Because of this, most of them
+follow another defacto limitations: they avoid using the characters
+``:``, ``\n``, and ``\x00`` anywhere in their encoded hash.
+In fact, for the most part they avoid using any characters except
+``a-zA-Z0-9./``, and ``$`` as an internal separator, though
+this can be violated on some systems if the user intervenes.
+
+.. note::
+ :mod:`passlib.hash.des_crypt` and :mod:`passlib.hash.ext_des_crypt`
+ do not follow this protocol, since they predate it by many years.
diff --git a/docs/lib/passlib.utils.des.rst b/docs/lib/passlib.utils.des.rst
new file mode 100644
index 0000000..f50cc95
--- /dev/null
+++ b/docs/lib/passlib.utils.des.rst
@@ -0,0 +1,17 @@
+=============================================
+:mod:`passlib.utils.des` - DES routines
+=============================================
+
+.. module:: passlib.utils.des
+ :synopsis: routines for performing DES encryption
+
+This module contains routines for encrypting blocks of data using the DES algorithm.
+
+They do not support multi-block operation or decryption,
+since they are designed for use in password hash algorithms
+such as :mod:`passlib.hash.des_crypt` and :mod:`passlib.hash.ext_des_crypt`.
+
+.. autofunction:: expand_des_key
+.. autofunction:: des_encrypt_block
+.. autofunction:: mdes_encrypt_int_block
+
diff --git a/docs/lib/passlib.utils.h64.rst b/docs/lib/passlib.utils.h64.rst
new file mode 100644
index 0000000..b5f249b
--- /dev/null
+++ b/docs/lib/passlib.utils.h64.rst
@@ -0,0 +1,42 @@
+================================================
+:mod:`passlib.utils.h64` - Hash-64 Codec helpers
+================================================
+
+
+.. module:: passlib.utils.h64
+ :synopsis: Hash-64 Codec helpers
+
+Many of the password hash algorithms in passlib
+use a encoding scheme very similar to (but not compatible with)
+the standard base64 encoding scheme. the main differences are that
+it assigns the characters *completely* different numeric values compared
+to base64, as well as using ``.`` instead of ``+`` in it's character set.
+
+This encoding system appears to have originated with des-crypt hash,
+but is used by md5-crypt, sha-256-crypt, and others.
+within passlib, this encoding is referred as ``hash64`` encoding,
+and this module contains various utilities functions for encoding
+and decoding strings in that format.
+
+.. note::
+ It may *look* like bcrypt uses this scheme,
+ when in fact bcrypt uses the standard base64 encoding scheme,
+ but with ``+`` replaced with ``.``.
+
+.. data:: CHARS
+
+ The character set used by the Hash-64 format.
+ Index in character set denotes 6-bit integer value.
+
+.. autofunction:: encode_3_offsets
+.. autofunction:: encode_2_offsets
+.. autofunction:: encode_1_offset
+
+.. autofunction:: decode_int12
+.. autofunction:: encode_int12
+
+.. autofunction:: decode_int24
+.. autofunction:: encode_int24
+
+.. autofunction:: decode_int64
+.. autofunction:: encode_int64
diff --git a/docs/lib/passlib.utils.md4.rst b/docs/lib/passlib.utils.md4.rst
new file mode 100644
index 0000000..fb0f388
--- /dev/null
+++ b/docs/lib/passlib.utils.md4.rst
@@ -0,0 +1,20 @@
+====================================================
+:mod:`passlib.utils.md4` - MD4-Digest implementation
+====================================================
+
+.. module:: passlib.utils.md4
+ :synopsis: implemented of MD4-Digest
+
+.. warning::
+
+ This digest is considered **VERY INSECURE**,
+ and not suitable for any new cryptographic activities.
+ Trivial-cost real-world attacks exist for all
+ password algorithms, stream ciphers, etc, that have
+ been based on MD4.
+ Do not use this hash or derived schemes unless you *really* have to.
+
+This module implements the MD4 hash algorithm in pure python,
+based on the `rfc 1320 <http://www.faqs.org/rfcs/rfc1320.html>`_ specification of MD4.
+
+.. autoclass:: md4
diff --git a/docs/lib/passlib.utils.pbkdf2.rst b/docs/lib/passlib.utils.pbkdf2.rst
new file mode 100644
index 0000000..7bd9ab9
--- /dev/null
+++ b/docs/lib/passlib.utils.pbkdf2.rst
@@ -0,0 +1,15 @@
+====================================================
+:mod:`passlib.utils.pbkdf2` - PBKDF2 algorithm support
+====================================================
+
+.. module:: passlib.utils.pbkdf2
+ :synopsis: implementation of PBKDF2 algorithm
+
+This module provides a single function, :func:`pbkdf2`,
+which provides the ability to generate an arbitrary
+length key using the PBKDF2 key derivation algorithm,
+as specified in `rfc 2898 <http://tools.ietf.org/html/rfc2898>`_.
+This function can be helpful in creating password hashes
+using schemes which have been based around the pbkdf2 algorithm.
+
+.. autofunction:: pbkdf2
diff --git a/docs/lib/passlib.utils.rst b/docs/lib/passlib.utils.rst
new file mode 100644
index 0000000..00df703
--- /dev/null
+++ b/docs/lib/passlib.utils.rst
@@ -0,0 +1,79 @@
+=============================================
+:mod:`passlib.utils` - Helper Functions
+=============================================
+
+.. module:: passlib.utils
+ :synopsis: helper functions for implementing crypt handlers
+
+Overview
+========
+This module contains a number of utility functions used by passlib
+to implement the builtin handlers, and other code within passlib.
+They may also be useful when implementing custom handlers for existing legacy formats.
+
+Decorators
+==========
+.. autofunction:: classproperty
+.. autofunction:: abstractmethod
+.. autofunction:: abstractclassmethod
+
+String Manipulation
+===================
+.. autofunction:: splitcomma
+
+Bytes Manipulation
+==================
+
+.. autofunction:: bytes_to_int
+.. autofunction:: int_to_bytes
+.. autofunction:: list_to_bytes
+.. autofunction:: bytes_to_list
+
+.. autofunction:: xor_bytes
+
+Randomness
+==========
+.. data:: rng
+
+ The random number generator used by passlib to generate
+ salt strings and other things which don't require a
+ cryptographically strong source of randomness.
+
+.. autofunction:: getrandbytes
+.. autofunction:: getrandstr
+
+Object Tests
+============
+.. autofunction:: is_crypt_handler
+
+.. todo::
+
+ .. autofunction:: is_crypt_context
+
+Crypt Handler Helpers
+=====================
+The following functions are used by passlib to do input validation
+for many of the implemented password schemes:
+
+.. autofunction:: norm_rounds
+
+.. autofunction:: gen_salt(salt, charset=H64_CHARS)
+
+.. autofunction:: norm_salt(salt, min_chars, max_chars=None, charset=H64_CHARS, gen_charset=None, name=None)
+
+Submodules
+==========
+There are also a few sub modules which provide additional utility functions:
+
+.. toctree::
+
+ passlib.utils.des
+ passlib.utils.h64
+ passlib.utils.md4
+ passlib.utils.pbkdf2
+
+.. todo::
+
+ document this module...
+
+ passlib.utils.handlers
diff --git a/docs/notes.txt b/docs/notes.txt
index 72fcc89..fcbfa01 100644
--- a/docs/notes.txt
+++ b/docs/notes.txt
@@ -182,9 +182,6 @@ references for hashes & passwords
http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html
http://www.openwall.com/john/interviews/SF-20060222-p3
-http://search.cpan.org/~zefram/Authen-Passphrase-0.007/lib/Authen/Passphrase.pm
-
-
===========
scrpyt
http://www.tarsnap.com/scrypt.html
diff --git a/docs/overview.rst b/docs/overview.rst
index 71cb8cb..51559c1 100644
--- a/docs/overview.rst
+++ b/docs/overview.rst
@@ -2,20 +2,10 @@
Library Overview
================
-BPS started life in 2003 as an in-house collection of small functions
-and tools which were frequently needed by the programmers at
-`Assurance Technologies <http://www.assurancetechnologies.com>`_.
-Over the years, it has accumlated a more small functions,
-but it has also acquired some modules which provide major
-new features that go above and beyond simple utility functions.
-Since we have benefited greatly from open source software,
-this library was released publically in 2009, in order
-to fill a few niches for which there is a need (password hashing,
-desktop interaction), as well as to simply give something
-back to the community.
+Passlib is a collection of routines for managing password hashes
+as found in unix /etc/shadow files, as returned by stdlib `crypt()`,
+as stored in mysql and postgres, and various other contexts.
-.. module:: passlib
- :synopsis: Root of all PassLib modules
+.. todo::
-Organization
-============
+ more documentation!
diff --git a/docs/lib/passlib.hash/quickstart.rst b/docs/quickstart.rst
index c6128f8..c6128f8 100644
--- a/docs/lib/passlib.hash/quickstart.rst
+++ b/docs/quickstart.rst
diff --git a/passlib/base.py b/passlib/base.py
index 09e5f89..53d48d4 100644
--- a/passlib/base.py
+++ b/passlib/base.py
@@ -21,10 +21,11 @@ import hashlib
import logging; log = logging.getLogger(__name__)
import time
import os
+from warnings import warn
#site
#libs
import passlib.hash as _hmod
-from passlib.utils import abstract_class_method, Undef, is_crypt_handler, splitcomma
+from passlib.utils import abstractclassmethod, Undef, is_crypt_handler, splitcomma
#pkg
#local
__all__ = [
@@ -85,8 +86,11 @@ def get_crypt_handler(name, default=Undef):
"resolve crypt algorithm name"
global _hmod
- ###normalize name
- ##name = name.replace("-","_").lower()
+ #normalize name
+ alt = name.replace("-","_").lower()
+ if alt != name:
+ warn("handler names be lower-case, and use underscores instead of hyphens: %r => %r" % (name, alt))
+ name = alt
#check if handler loaded
handler = getattr(_hmod, name, None)
diff --git a/passlib/hash/apr_md5_crypt.py b/passlib/hash/apr_md5_crypt.py
index 3c1932c..5eb45fa 100644
--- a/passlib/hash/apr_md5_crypt.py
+++ b/passlib/hash/apr_md5_crypt.py
@@ -1,15 +1,4 @@
-"""passlib.hash.apr_md5_crypt - Apache variant of md5-crypt algorithm
-
-This format is primarily used by Apache in htpasswd files.
-
-.. note::
- This format would be identical to md5-crypt,
- except for two things: it uses ``$apr1$`` as it's prefix
- when encoded, and inserts that constant into the hash calculation
- where md5-crypt would insert ``$1$``.
- Thus, the formats aren't compatible, nor the checksums they contain.
- Other than that, they have identical levels of security.
-"""
+"""passlib.hash.apr_md5_crypt - Apache variant of md5-crypt algorithm"""
#=========================================================
#imports
#=========================================================
diff --git a/passlib/hash/postgres_md5.py b/passlib/hash/postgres_md5.py
index 0efefe6..faa27e5 100644
--- a/passlib/hash/postgres_md5.py
+++ b/passlib/hash/postgres_md5.py
@@ -1,26 +1,4 @@
-"""passlib.hash.postgres_md5 - MD5-based algorithm used by Postgres for pg_shadow table
-
-This implements the md5-based hash algorithm used by Postgres to store
-passwords in the pg_shadow table.
-
-This algorithm shouldn't be used for any purpose besides Postgres interaction,
-it's a weak unsalted algorithm which could be attacked with a rainbow table
-built against common user names.
-
-.. warning::
- This algorithm is slightly different from most of the others,
- in that both encrypt() and verify() require you pass in
- the name of the user account via the required 'user' keyword,
- since postgres uses this in place of a salt :(
-
-Usage Example::
-
- >>> from passlib.hash import postgres_md5 as pm
- >>> pm.encrypt("mypass", user="postgres")
- 'md55fba2ea04fd36069d2574ea71c8efe9d'
- >>> pm.verify("mypass", 'md55fba2ea04fd36069d2574ea71c8efe9d', user="postgres")
- True
-"""
+"""passlib.hash.postgres_md5 - MD5-based algorithm used by Postgres for pg_shadow table"""
#=========================================================
#imports
#=========================================================
diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py
index 37b25b2..0a88df9 100644
--- a/passlib/utils/__init__.py
+++ b/passlib/utils/__init__.py
@@ -20,7 +20,7 @@ __all__ = [
#decorators
"classproperty",
"abstractmethod",
- "abstract_class_property",
+ "abstractclassmethod",
#byte manipulation
"bytes_to_list",
@@ -36,7 +36,7 @@ __all__ = [
#decorators
#=================================================================================
class classproperty(object):
- """Decorator which acts like a combination of classmethod+property (limited to read-only)"""
+ """Function decorator which acts like a combination of classmethod+property (limited to read-only properties)"""
def __init__(self, func):
self.im_func = func
@@ -57,9 +57,9 @@ def abstractmethod(func):
update_wrapper(wrapper, func)
return wrapper
-def abstract_class_method(func):
+def abstractclassmethod(func):
"""Class Method decorator which indicates this is a placeholder method which
- should be overridden by subclass.
+ should be overridden by subclass, and must be a classmethod.
If called directly, this method will raise an :exc:`NotImplementedError`.
"""
@@ -76,7 +76,7 @@ Undef = object() #singleton used as default kwd value in some functions
#protocol helpers
#==========================================================
def is_crypt_handler(obj):
- "check if obj follows CryptHandler api"
+ "check if object follows the :ref:`crypt handler api <crypt-handler-api>`"
return all(hasattr(obj, name) for name in (
"name",
"setting_kwds", "context_kwds",
@@ -96,7 +96,7 @@ def is_crypt_handler(obj):
#string helpers
#=================================================================================
def splitcomma(source):
- "split comma separated list into elements, stripping whitespace"
+ "split comma separated string into list elements, stripping whitespace and empty elements"
return [
elem.strip()
for elem in source.split(",")
@@ -143,14 +143,14 @@ def splitcomma(source):
## return out
def bytes_to_int(value):
- "decode bytes as single big-endian integer"
+ "decode string of bytes as single big-endian integer"
out = 0
for v in value:
out = (out<<8) | ord(v)
return out
def int_to_bytes(value, count):
- "encode integer into single big-endian byte string"
+ "encodes integer into single big-endian byte string"
assert value < (1<<(8*count)), "value too large for %d bytes: %d" % (count, value)
return ''.join(
chr((value>>s) & 0xff)
@@ -161,8 +161,8 @@ def int_to_bytes(value, count):
def list_to_bytes(value, bytes=None, order="big"):
"""Returns a multi-character string corresponding to a list of byte values.
- This is similar to :func:`int_to_bytes`, except that this a list of integers
- instead of a single encoded integer.
+ This is similar to :func:`int_to_bytes`, except that this returns a list
+ of integers, where each integer corresponds to a single byte of the input.
:arg value:
The list of integers to encode.
@@ -183,7 +183,7 @@ def list_to_bytes(value, bytes=None, order="big"):
Usage Example::
- >>> from passlib.util import list_to_bytes, bytes_to_list
+ >>> from passlib.utils import list_to_bytes, bytes_to_list
>>> list_to_bytes([4, 210], 4)
'\\x00\\x00\\x04\\xd2'
@@ -253,7 +253,7 @@ def bytes_to_list(value, order="big"):
_join = "".join
def xor_bytes(left, right):
- "bitwise-xor two byte-strings together"
+ "perform bitwise-xor of two byte-strings"
return _join(chr(ord(l) ^ ord(r)) for l, r in zip(left, right))
#=================================================================================
@@ -308,10 +308,10 @@ rng = random.Random(genseed())
#-----------------------------------------------------------------------
def getrandbytes(rng, count):
- """return string of *count* number of random bytes, using specified rng"""
+ """return byte-string containing *count* number of randomly generated bytes, using specified rng"""
#NOTE: would be nice if this was present in stdlib Random class
- ###just in case rng provides this (eg our SystemRandom subclass above)...
+ ###just in case rng provides this...
##meth = getattr(rng, "getrandbytes", None)
##if meth:
## return meth(count)
@@ -324,23 +324,23 @@ def getrandbytes(rng, count):
value //= 0xff
return buf.getvalue()
-def getrandstr(rng, alphabet, count):
- """return string of *size* number of chars, whose elements are drawn from specified alphabet"""
+def getrandstr(rng, charset, count):
+ """return character string containg *count* number of chars, whose elements are drawn from specified charset, using specified rng"""
#check alphabet & count
if count < 0:
raise ValueError, "count must be >= 0"
- letters = len(alphabet)
+ letters = len(charset)
if letters == 0:
raise ValueError, "alphabet must not be empty"
if letters == 1:
- return alphabet * count
+ return charset * count
#get random value, and write out to buffer
#XXX: break into chunks for large number of letters?
value = rng.randrange(0, letters**count)
buf = StringIO()
for i in xrange(count):
- buf.write(alphabet[value % letters])
+ buf.write(charset[value % letters])
value //= letters
assert value == 0
return buf.getvalue()
@@ -374,6 +374,7 @@ def norm_rounds(rounds, default_rounds, min_rounds, max_rounds, name="this crypt
return rounds
def gen_salt(count, charset=h64.CHARS):
+ "generate salt string of *count* chars using specified *charset*"
global rng
return getrandstr(rng, charset, count)
@@ -389,11 +390,12 @@ def norm_salt(salt, min_chars, max_chars=None, charset=h64.CHARS, gen_charset=No
:arg salt: user-provided salt
:arg min_chars: minimum number of chars in salt
:arg max_chars: maximum number of chars in salt (if omitted, same as min_chars)
- :param charset: character set that salt MUST be subset of
+ :param charset: character set that salt MUST be subset of (defaults to :)
:param gen_charset: optional character set to restrict to when generating new salts (defaults to charset)
:param name: optional name of handler, for inserting into error messages
:raises ValueError:
+
* if salt contains chars that aren't in salt_charset.
* if salt contains less than min_salt_chars characters.
@@ -422,27 +424,5 @@ def norm_salt(salt, min_chars, max_chars=None, charset=h64.CHARS, gen_charset=No
return salt
#=================================================================================
-#errors
-#=================================================================================
-
-###NOTE: not all handlers will raise these errors,
-### the only thing currently guaranteed is that they
-### will
-##
-##class HandlerError(ValueError):
-## "helper class for various errors used by some CryptHandlers"
-## message = None
-##
-## def __init__(self, msg=None):
-## ValueError.__init__(self, msg or self.message)
-##
-##class NoChecksumError(HandlerError):
-## "helper raised by CryptHandler.verify() when config string passed in instead of hash"
-## #helper for common message raised by handlers
-##
-## message = "hash lacks checksum (did you pass a config string into verify?)"
-
-
-#=================================================================================
#eof
#=================================================================================
diff --git a/passlib/utils/des.py b/passlib/utils/des.py
index 0851bb3..aea62d7 100644
--- a/passlib/utils/des.py
+++ b/passlib/utils/des.py
@@ -1,17 +1,3 @@
-"""passlib.utils.des -- DES encryption routines
-
-This module contains routines for encrypting blocks of data using the DES algorithm.
-
-They do not support multi-block operation or decryption,
-since they are designed for use in password hash algorithms
-such as ``lmhash`` and ``des-crypt``.
-
-.. function:: expand_des_key
-.. function:: des_encrypt_block
-.. function:: mdes_encrypt_int_block
-
-"""
-
"""
History
=======
diff --git a/passlib/utils/h64.py b/passlib/utils/h64.py
index 9e91cb7..4d472c2 100644
--- a/passlib/utils/h64.py
+++ b/passlib/utils/h64.py
@@ -1,22 +1,4 @@
-"""passlib.utils.h64 - hash64 encoding helpers
-
-many of the password hash algorithms in passlib
-use a encoding scheme very similar to, but not compatible with,
-the standard base64 encoding scheme. the main differences are that
-it uses ``.`` instead of ``+``, and assigns the
-characters *completely* different numeric values.
-
-this encoding system appears to have originated with des-crypt hash,
-but is used by md5-crypt, sha-256-crypt, and others.
-within passlib, this encoding is referred as ``hash64`` encoding,
-and this module contains various utilities functions for encoding
-and decoding strings in that format.
-
-.. note::
- It may *look* like bcrypt uses this scheme,
- when in fact bcrypt uses the standard base64 encoding scheme,
- but with ``+`` replaced with ``.``.
-"""
+"""passlib.utils.h64 - hash64 encoding helpers"""
#=================================================================================
#imports
#=================================================================================
@@ -34,10 +16,9 @@ __all__ = [
"encode_2_offsets",
"encode_1_offset",
- "decode_int12",
+ "decode_int12", "encode_int12"
"decode_int24", "encode_int24",
- "encode_int64",
-
+ "decode_int64", "encode_int64",
]
#=================================================================================
@@ -93,17 +74,17 @@ def encode_1_offset(buffer, o1):
# int <-> b64 string, used by des_crypt, ext_des_crypt
#=================================================================================
-##def decode_int(value):
-## "decode hash-64 format used by crypt into integer"
-## #FORMAT: little-endian, each char contributes 6 bits,
-## # char value = index in H64_CHARS string
-## try:
-## out = 0
-## for c in reversed(value):
-## out = (out<<6) + b64_decode_6bit(c)
-## return out
-## except KeyError:
-## raise ValueError, "invalid character in string"
+def decode_int(value):
+ "decode hash-64 format used by crypt into integer"
+ #FORMAT: little-endian, each char contributes 6 bits,
+ # char value = index in H64_CHARS string
+ try:
+ out = 0
+ for c in reversed(value):
+ out = (out<<6) + b64_decode_6bit(c)
+ return out
+ except KeyError:
+ raise ValueError, "invalid character in string"
def decode_int12(value):
"decode 2 chars of hash-64 format used by crypt, returning 12-bit integer"
@@ -112,8 +93,12 @@ def decode_int12(value):
except KeyError:
raise ValueError, "invalid character"
+def encode_int12(value):
+ "encode 2 chars of hash-64 format from a 12-bit integer"
+ return encode_6bit(value & 0x3f) + encode_6bit((value>>6) & 0x3f)
+
def decode_int24(value):
- "decode 4 chars of hash-64 format used by crypt, returning 24-bit integer"
+ "decode 4 chars of hash-64 format, returning 24-bit integer"
try:
return decode_6bit(value[0]) +\
(decode_6bit(value[1])<<6)+\
@@ -123,7 +108,7 @@ def decode_int24(value):
raise ValueError, "invalid character"
def encode_int24(value):
- "decode 2 chars of hash-64 format used by crypt, returning 12-bit integer"
+ "encode 4 chars of hash-64 format from a 24-bit integer"
return encode_6bit(value & 0x3f) + \
encode_6bit((value>>6) & 0x3f) + \
encode_6bit((value>>12) & 0x3f) + \
@@ -131,8 +116,12 @@ def encode_int24(value):
_RR9_1 = range(9,-1,-1)
+def decode_int64(value):
+ "decode 64-bit integer from 11 chars of hash-64 format"
+ return decode_int(value)
+
def encode_int64(value):
- "encode 64-bit integer to hash-64 format used by crypt, returning 11 chars"
+ "encode 64-bit integer to hash-64 format, returning 11 chars"
out = [None] * 10 + [ encode_6bit((value<<2)&0x3f) ]
value >>= 4
for i in _RR9_1:
diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py
index 6c09375..8e9fe1f 100644
--- a/passlib/utils/handlers.py
+++ b/passlib/utils/handlers.py
@@ -12,7 +12,7 @@ import time
import os
#site
#libs
-from passlib.utils import abstract_class_method, classproperty, h64, \
+from passlib.utils import abstractclassmethod, classproperty, h64, \
getrandstr, rng, Undef, is_crypt_handler
#pkg
#local
@@ -67,7 +67,7 @@ class CryptHandler(object):
#primary interface - primary methods implemented by each handler
#=========================================================
- @abstract_class_method
+ @abstractclassmethod
def genhash(cls, secret, config, **context):
"""encrypt secret to hash
@@ -355,7 +355,7 @@ class CryptHandler(object):
## #backend parsing routines - used by helpers below
## #=========================================================
##
-## @abstract_class_method
+## @abstractclassmethod
## def parse(cls, hash):
## """parse hash or config into dictionary.
##
@@ -388,7 +388,7 @@ class CryptHandler(object):
## verify() method can work properly.
## """
##
-## @abstract_class_method
+## @abstractclassmethod
## def render(cls, checksum=None, **settings):
## """render hash from checksum & settings (as returned by :meth:`parse`).
##
diff --git a/passlib/utils/md4.py b/passlib/utils/md4.py
index 550eff8..f01ecb0 100644
--- a/passlib/utils/md4.py
+++ b/passlib/utils/md4.py
@@ -24,7 +24,28 @@ def new(content=None):
return md4(content)
class md4(object):
- "md4 hash algorithm"
+ """pep-247 compatible implementation of MD4 hash algorithm
+
+ .. attribute:: digest_size
+
+ size of md4 digest in bytes (16 bytes)
+
+ .. method:: update
+
+ update digest by appending additional content
+
+ .. method:: copy
+
+ create clone of digest object, including current state
+
+ .. method:: digest
+
+ return bytes representing md4 digest of current content
+
+ .. method:: hexdigest
+
+ return hexdecimal version of digest
+ """
#FIXME: make this follow hash object PEP better.
#FIXME: this isn't threadsafe
#XXX: should we monkeypatch ourselves into hashlib for general use? probably wouldn't be nice.