summaryrefslogtreecommitdiff
path: root/passlib/handlers/digests.py
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-04-17 23:14:51 -0400
committerEli Collins <elic@assurancetechnologies.com>2012-04-17 23:14:51 -0400
commit64ab6fc89b497efa9169f11d55251e417c4db0ba (patch)
treeb3f6f5dc27b87a6bc90cb3686fa98239ee8ff053 /passlib/handlers/digests.py
parent8eb4c4d3b58eec6802c698ddbf357b2fd243a68c (diff)
parentcd029846fdc0c3d7ffc7f53caad4579e7e0e8725 (diff)
downloadpasslib-ironpython-support-dev.tar.gz
Merge from defaultironpython-support-dev
Diffstat (limited to 'passlib/handlers/digests.py')
-rw-r--r--passlib/handlers/digests.py62
1 files changed, 61 insertions, 1 deletions
diff --git a/passlib/handlers/digests.py b/passlib/handlers/digests.py
index ec08056..22c1c6a 100644
--- a/passlib/handlers/digests.py
+++ b/passlib/handlers/digests.py
@@ -9,7 +9,7 @@ import logging; log = logging.getLogger(__name__)
from warnings import warn
#site
#libs
-from passlib.utils import to_native_str
+from passlib.utils import to_native_str, to_bytes, render_bytes, consteq
from passlib.utils.compat import bascii_to_str, bytes, unicode, str_to_uascii
import passlib.utils.handlers as uh
from passlib.utils.md4 import md4
@@ -76,5 +76,65 @@ hex_sha256 = create_hex_hash(hashlib.sha256, "sha256")
hex_sha512 = create_hex_hash(hashlib.sha512, "sha512")
#=========================================================
+# htdigest
+#=========================================================
+class htdigest(object):
+ """htdigest hash function.
+
+ .. todo::
+ document this hash
+ """
+ name = "htdigest"
+ setting_kwds = ()
+ context_kwds = ("user", "realm")
+
+ @classmethod
+ def encrypt(cls, secret, user, realm, encoding="utf-8"):
+ # NOTE: deliberately written so that raw bytes are passed through
+ # unchanged, encoding only used to handle unicode values.
+ uh.validate_secret(secret)
+ if isinstance(secret, unicode):
+ secret = secret.encode(encoding)
+ user = to_bytes(user, encoding, "user")
+ realm = to_bytes(realm, encoding, "realm")
+ data = render_bytes("%s:%s:%s", user, realm, secret)
+ return hashlib.md5(data).hexdigest()
+
+ @classmethod
+ def _norm_hash(cls, hash):
+ "normalize hash to native string, and validate it"
+ hash = to_native_str(hash, errname="hash")
+ if len(hash) != 32:
+ raise uh.exc.MalformedHashError(cls, "wrong size")
+ for char in hash:
+ if char not in uh.LC_HEX_CHARS:
+ raise uh.exc.MalformedHashError(cls, "invalid chars in hash")
+ return hash
+
+ @classmethod
+ def verify(cls, secret, hash, user, realm, encoding="utf-8"):
+ hash = cls._norm_hash(hash)
+ other = cls.encrypt(secret, user, realm, encoding)
+ return consteq(hash, other)
+
+ @classmethod
+ def identify(cls, hash):
+ try:
+ cls._norm_hash(hash)
+ except ValueError:
+ return False
+ return True
+
+ @classmethod
+ def genconfig(cls):
+ return None
+
+ @classmethod
+ def genhash(cls, secret, config, user, realm, encoding="utf-8"):
+ if config is not None:
+ cls._norm_hash(config)
+ return cls.encrypt(secret, user, realm, encoding)
+
+#=========================================================
#eof
#=========================================================