# Path: wsse/utils.py
# _TOKEN_RE = re.compile(
# 	r'''
# 		(?P<key>\w+)\s*=\s* # Key consists of only alphanumerics
# 		(?P<quote>["']?)    # Optional quote character.
# 		(?P<value>.*?)      # Value is a non greedy match
# 		(?P=quote)          # Closing quote equals the first.
# 		($|,)               # Entry ends with comma or end of string
# 	''', re.VERBOSE)
# _TS_OFFSET_RE = re.compile(
# 	r'''
# 		^
# 		(?P<timestamp>.+)    # Main part of timestamp
# 		(?P<direction>\+|\-) # Offset direction (+ or -)
# 		(?P<hour>\d{2})      # Hour offset (HH)
# 		(?P<minute>\d{2})    # Minute offset (MM)
# 		$
# 	''', re.VERBOSE)
# _STORES = {}
# class TokenBuilder(object):
# 	def __init__(self, username, password):
# 	def make_token(self, nonce = None, timestamp = None):
# def make_token(username, password, nonce, timestamp, ts_format = None,
# 	algorithm = None):
# def check_token(token, get_password = lambda username: username):
# def _parse_token(token):
# def _parse_timestamp(timestamp):
# def _random_string(length = None, allowed_chars = None):
# def _b64_digest(*args, **kwargs):
# def _get_digest_algorithm(name = None):
# def _get_nonce_store():
# def _to_bytes(s):
# def _from_bytes(b):
# def _django_header(header):
# def _make_tz_aware(dt):
# 
# Path: wsse/settings.py
# TIMESTAMP_DURATION = 2 * 60 * 60
# DRIFT_OFFSET = 2 * 60
# TIMESTAMP_FORMATS = [
# 	'%Y-%m-%dT%H:%M:%SZ',    # ISO 8601 in UTC (Z specifies 0 offset)
# 	'%Y-%m-%dT%H:%M:%S',     # ISO 8601 without timezone - assumed to be UTC
# 	'%Y-%m-%dT%H:%M:%S.%fZ', # ISO 8601 with microseconds in UTC
# 	'%Y-%m-%dT%H:%M:%S.%f',  # ISO 8601 with microseconds (assumed UTC)
# 	'%Y-%m-%dT%H:%M:%S%z',   # ISO 8601 with UTC offset
# 	'%Y-%m-%dT%H:%M:%S.%f%z' # ISO 8601 with microseconds and UTC offset
# 	]
# NONCE_LENGTH = 64
# NONCE_STORE = 'wsse.server.default.store.SQLiteNonceStore'
# NONCE_STORE_ARGS = (':memory:',)
# REQUEST_HEADER = 'X-WSSE'
# SECURITY_CHECK_NONCE = True
# SECURITY_CHECK_TIMESTAMP = True
# ALLOWED_DIGEST_ALGORITHMS = ['SHA256']
# PROHIBITED_DIGEST_ALGORITHMS = ['SHA1', 'MD5']
# SECRET_KEY_LENGTH = 64
# LOGGER_NAME = 'wsse'
# 
# Path: wsse/compat.py

# 
# Path: wsse/server/django/wsse/models.py
# class UserSecret(models.Model):
# 	'''
# 	The `UserSecret` object connects every user to their secret key. The secret
# 	key can be deleted to prevent access without affecting the user.
# 	'''
# 	user = models.OneToOneField(User, on_delete = models.CASCADE,
# 		db_index = True)
# 	secret = models.CharField(max_length = settings.SECRET_KEY_LENGTH,
# 		default = _generate_secret, blank = True, null = False)


import contextlib
import hashlib
import base64
import datetime
import itertools
from rest_framework.test import APITestCase, APIRequestFactory
from rest_framework import status
from django.contrib.auth.models import User
from django.utils import timezone
from wsse import utils, settings
from wsse.compat import reverse_lazy
from wsse.server.django.wsse.models import UserSecret
		'''
		Perform a request with an invalid timestamp format.
		Authentication should not succeed.
		'''
		now = timezone.now()
		timestamp = now.strftime("%m/%d/%Y, %M:%S.%f")

		with self.http_auth(self.make_header(timestamp = timestamp)):
			response = self.client.get(self.base_url)

		self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

	def test_expired_timestamp(self):
		'''
		Authenticate an expired timestamp. The authentication should not succeed.
		'''
		now = timezone.now() - datetime.timedelta(
			seconds = settings.TIMESTAMP_DURATION + 1)
		timestamp = now.strftime('%Y-%m-%dT%H:%M:%S.%fZ')

		with self.http_auth(self.make_header(timestamp = timestamp)):
			response = self.client.get(self.base_url)

		self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

	def test_future_timestamp(self):
		'''
		Authenticate a future timestamp. The authentication should not succeed.
		'''
		now = timezone.now() + datetime.timedelta(

# Path: wsse/utils.py
# _TOKEN_RE = re.compile(
# 	r'''
# 		(?P<key>\w+)\s*=\s* # Key consists of only alphanumerics
# 		(?P<quote>["']?)    # Optional quote character.
# 		(?P<value>.*?)      # Value is a non greedy match
# 		(?P=quote)          # Closing quote equals the first.
# 		($|,)               # Entry ends with comma or end of string
# 	''', re.VERBOSE)
# _TS_OFFSET_RE = re.compile(
# 	r'''
# 		^
# 		(?P<timestamp>.+)    # Main part of timestamp
# 		(?P<direction>\+|\-) # Offset direction (+ or -)
# 		(?P<hour>\d{2})      # Hour offset (HH)
# 		(?P<minute>\d{2})    # Minute offset (MM)
# 		$
# 	''', re.VERBOSE)
# _STORES = {}
# class TokenBuilder(object):
# 	def __init__(self, username, password):
# 	def make_token(self, nonce = None, timestamp = None):
# def make_token(username, password, nonce, timestamp, ts_format = None,
# 	algorithm = None):
# def check_token(token, get_password = lambda username: username):
# def _parse_token(token):
# def _parse_timestamp(timestamp):
# def _random_string(length = None, allowed_chars = None):
# def _b64_digest(*args, **kwargs):
# def _get_digest_algorithm(name = None):
# def _get_nonce_store():
# def _to_bytes(s):
# def _from_bytes(b):
# def _django_header(header):
# def _make_tz_aware(dt):
# 
# Path: wsse/settings.py
# TIMESTAMP_DURATION = 2 * 60 * 60
# DRIFT_OFFSET = 2 * 60
# TIMESTAMP_FORMATS = [
# 	'%Y-%m-%dT%H:%M:%SZ',    # ISO 8601 in UTC (Z specifies 0 offset)
# 	'%Y-%m-%dT%H:%M:%S',     # ISO 8601 without timezone - assumed to be UTC
# 	'%Y-%m-%dT%H:%M:%S.%fZ', # ISO 8601 with microseconds in UTC
# 	'%Y-%m-%dT%H:%M:%S.%f',  # ISO 8601 with microseconds (assumed UTC)
# 	'%Y-%m-%dT%H:%M:%S%z',   # ISO 8601 with UTC offset
# 	'%Y-%m-%dT%H:%M:%S.%f%z' # ISO 8601 with microseconds and UTC offset
# 	]
# NONCE_LENGTH = 64
# NONCE_STORE = 'wsse.server.default.store.SQLiteNonceStore'
# NONCE_STORE_ARGS = (':memory:',)
# REQUEST_HEADER = 'X-WSSE'
# SECURITY_CHECK_NONCE = True
# SECURITY_CHECK_TIMESTAMP = True
# ALLOWED_DIGEST_ALGORITHMS = ['SHA256']
# PROHIBITED_DIGEST_ALGORITHMS = ['SHA1', 'MD5']
# SECRET_KEY_LENGTH = 64
# LOGGER_NAME = 'wsse'
# 
# Path: wsse/compat.py

# 
# Path: wsse/server/django/wsse/models.py
# class UserSecret(models.Model):
# 	'''
# 	The `UserSecret` object connects every user to their secret key. The secret
# 	key can be deleted to prevent access without affecting the user.
# 	'''
# 	user = models.OneToOneField(User, on_delete = models.CASCADE,
# 		db_index = True)
# 	secret = models.CharField(max_length = settings.SECRET_KEY_LENGTH,
# 		default = _generate_secret, blank = True, null = False)


# Path: wsse/server/drf/tests/test_authentication.py
import contextlib
import hashlib
import base64
import datetime
import itertools
from rest_framework.test import APITestCase, APIRequestFactory
from rest_framework import status
from django.contrib.auth.models import User
from django.utils import timezone
from wsse import utils, settings
from wsse.compat import reverse_lazy
from wsse.server.django.wsse.models import UserSecret

		'''
		Perform a request with an invalid timestamp format.
		Authentication should not succeed.
		'''
		now = timezone.now()
		timestamp = now.strftime("%m/%d/%Y, %M:%S.%f")

		with self.http_auth(self.make_header(timestamp = timestamp)):
			response = self.client.get(self.base_url)

		self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

	def test_expired_timestamp(self):
		'''
		Authenticate an expired timestamp. The authentication should not succeed.
		'''
		now = timezone.now() - datetime.timedelta(
			seconds = settings.TIMESTAMP_DURATION + 1)
		timestamp = now.strftime('%Y-%m-%dT%H:%M:%S.%fZ')

		with self.http_auth(self.make_header(timestamp = timestamp)):
			response = self.client.get(self.base_url)

		self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

	def test_future_timestamp(self):
		'''
		Authenticate a future timestamp. The authentication should not succeed.
		'''
		now = timezone.now() + datetime.timedelta(

			seconds = settings.TIMESTAMP_DURATION + 1)