authentik.stages.authenticator.util
Authenticator utils
1"""Authenticator utils""" 2 3import random 4import string 5from binascii import Error, unhexlify 6from os import urandom 7 8from django.core.exceptions import ValidationError 9 10 11def hex_validator(length=0): 12 """ 13 Returns a function to be used as a model validator for a hex-encoded 14 CharField. This is useful for secret keys of all kinds:: 15 16 def key_validator(value): 17 return hex_validator(20)(value) 18 19 key = models.CharField(max_length=40, 20 validators=[key_validator], help_text='A hex-encoded 20-byte secret key') 21 22 :param int length: If greater than 0, validation will fail unless the 23 decoded value is exactly this number of bytes. 24 25 :rtype: function 26 27 >>> hex_validator()('0123456789abcdef') 28 >>> hex_validator(8)(b'0123456789abcdef') 29 >>> hex_validator()('phlebotinum') # doctest: +IGNORE_EXCEPTION_DETAIL 30 Traceback (most recent call last): 31 ... 32 ValidationError: ['phlebotinum is not valid hex-encoded data.'] 33 >>> hex_validator(9)('0123456789abcdef') # doctest: +IGNORE_EXCEPTION_DETAIL 34 Traceback (most recent call last): 35 ... 36 ValidationError: ['0123456789abcdef does not represent exactly 9 bytes.'] 37 """ 38 39 def _validator(value): 40 try: 41 if isinstance(value, str): 42 value = value.encode() 43 44 unhexlify(value) 45 except Error: 46 raise ValidationError(f"{value} is not valid hex-encoded data.") from None 47 48 if (length > 0) and (len(value) != length * 2): 49 raise ValidationError(f"{value} does not represent exactly {length} bytes.") 50 51 return _validator 52 53 54def random_hex(length=20): 55 """ 56 Returns a string of random bytes encoded as hex. 57 58 This uses :func:`os.urandom`, so it should be suitable for generating 59 cryptographic keys. 60 61 :param int length: The number of (decoded) bytes to return. 62 63 :returns: A string of hex digits. 64 :rtype: str 65 66 """ 67 return urandom(length).hex() 68 69 70def random_number_token(length=6): 71 """ 72 Returns a string of random digits encoded as string. 73 74 :param int length: The number of digits to return. 75 76 :returns: A string of decimal digits. 77 :rtype: str 78 79 """ 80 rand = random.SystemRandom() 81 82 if hasattr(rand, "choices"): 83 digits = rand.choices(string.digits, k=length) 84 else: 85 digits = (rand.choice(string.digits) for i in range(length)) 86 87 return "".join(digits)
def
hex_validator(length=0):
12def hex_validator(length=0): 13 """ 14 Returns a function to be used as a model validator for a hex-encoded 15 CharField. This is useful for secret keys of all kinds:: 16 17 def key_validator(value): 18 return hex_validator(20)(value) 19 20 key = models.CharField(max_length=40, 21 validators=[key_validator], help_text='A hex-encoded 20-byte secret key') 22 23 :param int length: If greater than 0, validation will fail unless the 24 decoded value is exactly this number of bytes. 25 26 :rtype: function 27 28 >>> hex_validator()('0123456789abcdef') 29 >>> hex_validator(8)(b'0123456789abcdef') 30 >>> hex_validator()('phlebotinum') # doctest: +IGNORE_EXCEPTION_DETAIL 31 Traceback (most recent call last): 32 ... 33 ValidationError: ['phlebotinum is not valid hex-encoded data.'] 34 >>> hex_validator(9)('0123456789abcdef') # doctest: +IGNORE_EXCEPTION_DETAIL 35 Traceback (most recent call last): 36 ... 37 ValidationError: ['0123456789abcdef does not represent exactly 9 bytes.'] 38 """ 39 40 def _validator(value): 41 try: 42 if isinstance(value, str): 43 value = value.encode() 44 45 unhexlify(value) 46 except Error: 47 raise ValidationError(f"{value} is not valid hex-encoded data.") from None 48 49 if (length > 0) and (len(value) != length * 2): 50 raise ValidationError(f"{value} does not represent exactly {length} bytes.") 51 52 return _validator
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
random_hex(length=20):
55def random_hex(length=20): 56 """ 57 Returns a string of random bytes encoded as hex. 58 59 This uses :func:`os.urandom`, so it should be suitable for generating 60 cryptographic keys. 61 62 :param int length: The number of (decoded) bytes to return. 63 64 :returns: A string of hex digits. 65 :rtype: str 66 67 """ 68 return urandom(length).hex()
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
def
random_number_token(length=6):
71def random_number_token(length=6): 72 """ 73 Returns a string of random digits encoded as string. 74 75 :param int length: The number of digits to return. 76 77 :returns: A string of decimal digits. 78 :rtype: str 79 80 """ 81 rand = random.SystemRandom() 82 83 if hasattr(rand, "choices"): 84 digits = rand.choices(string.digits, k=length) 85 else: 86 digits = (rand.choice(string.digits) for i in range(length)) 87 88 return "".join(digits)
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