import hashlib import hmac from persistent.mapping import PersistentMapping from zope.annotation.interfaces import IAnnotations from zope.interface import implements from AccessControl.AuthEncoding import pw_encrypt from AccessControl.AuthEncoding import pw_validate from Products.remember.config import ANNOT_KEY from Products.remember.interfaces import IHashPW class BaseHash(object): """ Abstract base class for actual hashing implementations. """ implements(IHashPW) def __init__(self, context): self.context = context def isAvailable(self): return True def hashPassword(self, password): raise NotImplementedError def validate(self, reference, attempt): """ Check to see if the reference is a hash of the attempt. """ return self.hashPassword(attempt) == reference class BCryptHash(BaseHash): """ Adapts from IAnnotatable to IHashPW. Uses bcrypt to hash the password """ try: import bcrypt except ImportError: bcrypt = None def __init__(self, context): self.context = context if self.bcrypt is None: return annotations = IAnnotations(context) storage = annotations.setdefault(ANNOT_KEY, PersistentMapping()) storage.setdefault('bcrypt_salt', self.bcrypt.gensalt()) self.storage = storage def isAvailable(self): return self.bcrypt is not None def hashPassword(self, password): """ Return a hashed version of password using bcrypt """ return self.bcrypt.hashpw(password, self.storage['bcrypt_salt']) class SHAHash(BaseHash): """ Adapts from IAnnotatable to IHashPW. Uses SHA to hash the password """ def hashPassword(self, password): """ Return a hashed version of password using SHA """ return hashlib.sha1(password).hexdigest() class HMACHash(BaseHash): """ Adapts from IAnnotatable to IHashPW. Uses SHA to hash the password """ def __init__(self, context): self.context = context key = str(context) annotations = IAnnotations(context) storage = annotations.setdefault(ANNOT_KEY, PersistentMapping()) storage.setdefault('hmac_key', key) self.storage = storage def hashPassword(self, password): """ Return a hashed version of password using SHA """ return hmac.new(self.storage['hmac_key'], password, hashlib.sha1 ).hexdigest() class ZAuthHash(BaseHash): """ Adapts from IAnnotatable to IHashPW. Uses Zope 2's AccessControl.AuthEncoding module to hash the password. """ def hashPassword(self, password): """ Delegate to AccessControl.AuthEncoding. """ return pw_encrypt(password) def validate(self, reference, attempt): """ Check to see if the reference is a hash of the attempt. """ return pw_validate(reference, attempt)