Source code for wasp_general.crypto.kdf

# -*- coding: utf-8 -*-
# wasp_general/crypto/kdf.py
#
# Copyright (C) 2017 the wasp-general authors and contributors
# <see AUTHORS file>
#
# This file is part of wasp-general.
#
# Wasp-general is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Wasp-general is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with wasp-general.  If not, see <http://www.gnu.org/licenses/>.

# noinspection PyUnresolvedReferences
from wasp_general.version import __author__, __version__, __credits__, __license__, __copyright__, __email__
# noinspection PyUnresolvedReferences
from wasp_general.version import __status__

from Crypto.Protocol.KDF import PBKDF2

from wasp_general.verify import verify_type, verify_value
from wasp_general.crypto.hmac import WHMAC
from wasp_general.crypto.random import random_bytes


[docs]class WPBKDF2: """ Wrapper for PyCrypto PBKDF2 implementation with NIST recommendation and HMAC is used as pseudorandom function NIST recommendation can be read here: http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf (Recommendation for Password-Based Key Derivation) """ __minimum_key_length__ = 20 """ Minimum key length is specified at Appendix A, Section A.1 of Recommendation for Password-Based Key Derivation by NIST """ __minimum_salt_length__ = 16 """ Minimum salt length is specified at Section 5.1 of Recommendation for Password-Based Key Derivation by NIST """ __default_salt_length__ = 64 """ Salt length value used by default """ __default_digest_generator_name__ = 'SHA256' """ Hash-generator that is used by default """ __minimum_iterations_count__ = 1000 """ Minimum iteration Count is specified at Section 5.2 of Recommendation for Password-Based Key Derivation by NIST """ __default_iterations_count__ = 1000 """ The iteration count used by default """ __default_derived_key_length__ = 16 """ Length of derived key used by default """ @verify_type(key=(str, bytes), salt=(bytes, None), derived_key_length=(int, None)) @verify_type(iterations_count=(int, None), hmac=(WHMAC, None)) @verify_value(key=lambda x: x is None or len(x) >= WPBKDF2.__minimum_key_length__) @verify_value(salt=lambda x: x is None or len(x) >= WPBKDF2.__minimum_salt_length__) @verify_value(iterations_count=lambda x: x is None or x >= WPBKDF2.__minimum_iterations_count__) def __init__(self, key, salt=None, derived_key_length=None, iterations_count=None, hmac=None): """ Generate new key (derived key) with PBKDF2 algorithm :param key: password :param salt: salt to use (if no salt was specified, then it will be generated automatically) :param derived_key_length: length of byte-sequence to generate :param iterations_count: iteration count :param hmac: WHMAC object to use with PBKDF2 """ self.__salt = salt if salt is not None else self.generate_salt() if derived_key_length is None: derived_key_length = self.__default_derived_key_length__ if iterations_count is None: iterations_count = self.__default_iterations_count__ if hmac is None: hmac = WHMAC(self.__default_digest_generator_name__) self.__derived_key = PBKDF2( key, self.__salt, dkLen=derived_key_length, count=iterations_count, prf=hmac.hash )
[docs] def salt(self): """ Return salt value (that was given in constructor or created automatically) :return: bytes """ return self.__salt
[docs] def derived_key(self): """ Return derived key :return: bytes """ return self.__derived_key
[docs] @classmethod @verify_type(length=(int, None)) @verify_value(length=lambda x: x is None or x >= WPBKDF2.__minimum_salt_length__) def generate_salt(cls, length=None): """ Generate salt that can be used by this object :param length: target salt length :return: bytes """ if length is None: length = cls.__default_salt_length__ return random_bytes(length)