Source code for django_otp.util

from binascii import unhexlify
from os import urandom
import random
import string

from django.core.exceptions import ValidationError

[docs] def hex_validator(length=0): """ Returns a function to be used as a model validator for a hex-encoded CharField. This is useful for secret keys of all kinds:: def key_validator(value): return hex_validator(20)(value) key = models.CharField(max_length=40, validators=[key_validator], help_text='A hex-encoded 20-byte secret key') :param int length: If greater than 0, validation will fail unless the decoded value is exactly this number of bytes. :rtype: function >>> hex_validator()('0123456789abcdef') >>> hex_validator(8)(b'0123456789abcdef') >>> hex_validator()('phlebotinum') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValidationError: ['phlebotinum is not valid hex-encoded data.'] >>> hex_validator(9)('0123456789abcdef') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValidationError: ['0123456789abcdef does not represent exactly 9 bytes.'] """ def _validator(value): try: if isinstance(value, str): value = value.encode() unhexlify(value) except Exception: raise ValidationError('{0} is not valid hex-encoded data.'.format(value)) if (length > 0) and (len(value) != length * 2): raise ValidationError( '{0} does not represent exactly {1} bytes.'.format(value, length) ) return _validator
[docs] def random_hex(length=20): """ Returns a string of random bytes encoded as hex. This uses :func:`os.urandom`, so it should be suitable for generating cryptographic keys. :param int length: The number of (decoded) bytes to return. :returns: A string of hex digits. :rtype: str """ return urandom(length).hex()
[docs] def random_number_token(length=6): """ Returns a string of random digits encoded as string. :param int length: The number of digits to return. :returns: A string of decimal digits. :rtype: str """ rand = random.SystemRandom() if hasattr(rand, 'choices'): digits = rand.choices(string.digits, k=length) else: digits = (rand.choice(string.digits) for i in range(length)) return ''.join(digits)