def test_login_after_regenerate_hotp(journalist_app, test_journo): """Test that journalists can login after resetting their HOTP 2fa""" otp_secret = 'aaaaaa' b32_otp_secret = b32encode(unhexlify(otp_secret)) # edit hotp with journalist_app.test_client() as app: _login_user(app, test_journo) with InstrumentedApp(journalist_app) as ins: resp = app.post('/account/reset-2fa-hotp', data=dict(otp_secret=otp_secret)) # valid otp secrets should redirect ins.assert_redirects(resp, '/account/2fa') resp = app.post('/account/2fa', data=dict(token=HOTP(b32_otp_secret).at(0))) # successful verificaton should redirect to /account/account ins.assert_redirects(resp, '/account/account') # log out app.get('/logout') # start a new client/context to be sure we've cleared the session with journalist_app.test_client() as app: with InstrumentedApp(journalist_app) as ins: # login with new 2fa secret should redirect to index page resp = app.post('/login', data=dict(username=test_journo['username'], password=test_journo['password'], token=HOTP(b32_otp_secret).at(1))) ins.assert_redirects(resp, '/')
def OTP_verification(OTP_value): # Lay sessionID cua user session_id = 'abacavasdf' data = None counter, OTP_check, time_create = None, None, None # Neu file ton tai va khac rong if not path.isfile('./OTP.json') or read_file('./OTP.json') == b'': print('OTP expires!!!') else: data = read_json_file('./OTP.json') for i in reversed(range(len(data["OTP"]))): dict = data["OTP"][i] if session_id in dict: counter = dict[session_id] base32secret = dict['base32secret'] time_create = dict['time_create'] break time_verify = datetime.now().strftime('%Y%m%d%H%M%S%f') #2020 10 28 02 30 08 743182 #2020 10 28 02 35 08 743183 if time_create is not None and int(time_verify) - int( time_create) <= 500000000: hotp = HOTP(base32secret) if hotp.verify(OTP_value, counter): print('Correct') else: print("OTP is wrong!!") else: print("OTP expires!!!")
def create(request): """ Verify the otp and send to the user its token Parameters ---------- request : Request the api request Returns ---------- Response confirm that the user is signup """ user, count_type = retrieve_user(request) print(user, count_type) print(request.data["otp"]) otp = OneTimePassword.objects.get(user=user) key = base64.b32encode(return_value(user.name).encode()) code = HOTP(key) if code.verify(request.data["otp"], otp.counter) and otp.isValid: otp.isValid = False otp.save() user.is_active = True user.save() token, created = Token.objects.get_or_create(user=user) return Response({"Token": token.key}) else: raise WrongCode()
def OTP_verification(request, OTP_value): # Lay sessionID cua user a = request.session session_id = a.session_key data = None counter, OTP_check, time_create = None, None, None # Neu file ton tai va khac rong if file_is_not_existed('./OTP.json'): # print('OTP expires!!!') return -1 else: data = read_json_file('./OTP.json') for i in reversed(range(len(data["OTP"]))): dict = data["OTP"][i] if session_id in dict: counter = dict[session_id] base32secret = dict['base32secret'] time_create = dict['time_create'] break time_verify = datetime.now().strftime('%Y%m%d%H%M%S%f') # 2020 10 28 02 30 08 743182 # 2020 10 28 02 35 08 743183 if time_create is not None and int(time_verify) - int( time_create) <= 500000000: hotp = HOTP(base32secret) if hotp.verify(OTP_value, counter): return 1 else: return 0 else: return -1
def OTP_synchronous_generator(license_id, downloader, username, phone, expDate, random_code): # Static random (6 digits) lay tu database static_random = 'asfb86' expDate = expDate.strftime('%Y%m%d%H%M%S%f') hash_value = hash_generator(license_id + downloader, username + phone, expDate + static_random) hash_value_base32 = b32encode(hash_value.encode('ascii')) hotp = HOTP(hash_value_base32) OTP_value = hotp.at(int(random_code)) return OTP_value
def post(request, pk): user = User.objects.get(pk=pk) keygen = generateKey() key = base64.b32encode(keygen.returnValue(user.phone).encode()) OTP = HOTP(key) otp_data = request.data['otp'] if OTP.verify(otp_data, user.verify_count): user.verified = True user.save() return Response({'message': f'{user.email} verified', 'user': UserSerializer(user, context={'request': request}).data}, status.HTTP_200_OK) return Response({'message': "OTP is wrong or has expired"}, status.HTTP_400_BAD_REQUEST)
def create(request): """ send a new otp to the user Parameters ---------- request : Request the api request Returns ---------- Response confirm that the otp has been sent """ user, count_type = retrieve_user(request) otp = OneTimePassword.objects.get(user=user) minute = timedelta(0, 21600) time = datetime.now() - otp.last_modification.replace(tzinfo=None) if time > minute or count_type == 'email': otp.counter += 1 otp.isValid = True otp.save() key = base64.b32encode(return_value(user.name).encode()) code = HOTP(key) send_password(user, otp, count_type, code) return Response( {"message": "Your code has been send as your email or phone"}, status=201) else: raise ToSoon(detail={"error": 4, "time": 21600 - time.seconds})
def create(self, request): """ Create a new user, and send the otp to the user Parameters ---------- request : Request the api request Returns ---------- Response confirm that the user is signup """ serializer = self.get_serializer(data=request.data) if serializer.is_valid(False): user = serializer.save() otp = OneTimePassword.objects.create(user=user) otp.save() key = base64.b32encode(return_value(user.name).encode()) code = HOTP(key) send_password(user, otp, self.request.query_params.get('type'), code) return Response( { "message": "You are signup, your code has been send as your email or phone" }, status=201) else: raise AlreadyUsed()
def OTP_generator(license_id, downloader, username, phone, expDate, random_code): timeNowCreate = datetime.now() time_create = timeNowCreate.minute hash_value = hash_generator(license_id + downloader, username + phone, expDate + "asfb86") hash_value_base32 = b32encode(hash_value.encode('ascii')) hotp = HOTP(hash_value_base32) return time_create, hotp
def OTP_generator(): # Lay sessionID cua user session_id = 'abacavasdf' base32secret = random_base32() hotp = HOTP(base32secret) counter = random_digit() OTP_value = hotp.at(counter) time_create = datetime.now().strftime('%Y%m%d%H%M%S%f') # Tao data cho file json dict = { session_id: counter, 'base32secret': base32secret, 'time_create': time_create } # Neu file ton tai va khac rong if not path.isfile('./OTP.json') or read_file('./OTP.json') == b'': generate_json_file('./OTP.json', 'OTP', dict) else: append_json_file('./OTP.json', 'OTP', dict, session_id) print(OTP_value) return OTP_value
def OTP_generator(request): # Lay sessionID cua user # a = ShareFile.objects.latest('date_create') a = request.session session_id = a.session_key base32secret = random_base32() hotp = HOTP(base32secret) counter = random_digit() OTP_value = hotp.at(counter) time_create = datetime.now().strftime('%Y%m%d%H%M%S%f') # Tao data cho file json dict = { session_id: counter, 'base32secret': base32secret, 'time_create': time_create } # Neu file ton tai va khac rong if file_is_not_existed('./OTP.json'): generate_json_file('./OTP.json', 'OTP', dict) else: append_json_file('./OTP.json', 'OTP', dict, session_id) return OTP_value
class TwoFactorCode: def __init__(self, name, issuer, codetype, codestr, counter, pos, ui, imagedata): # generate the uuid used as the dict key later # we want this to be a string self.uuid = uuid4().__str__() # grab values from call self.name = name self.issuer = issuer self.codetype = codetype self.codestr = codestr self.ui = ui self.counter = counter self.imagedata = imagedata self.pos = pos # check code type, make code object for type, # or throw exception if not recognized if codetype == 'totp': self.code = TOTP(self.codestr) self.curcode = self.code.now() elif codetype == 'hotp': self.code = HOTP(self.codestr) self.curcode = self.code.at(self.counter) else: raise TypeError('codetype was not hotp or totp') def set_counter(self, value): # set the counter to a specified value if self.counter is not None: self.counter = value.__int__() def get_current_code(self): # return current code (plaintext) if self.codetype == 'totp': return self.code.now().__str__() elif self.codetype == 'hotp': return self.code.at(self.counter).__str__()
def __init__(self, name, issuer, codetype, codestr, counter, pos, ui, imagedata): # generate the uuid used as the dict key later # we want this to be a string self.uuid = uuid4().__str__() # grab values from call self.name = name self.issuer = issuer self.codetype = codetype self.codestr = codestr self.ui = ui self.counter = counter self.imagedata = imagedata self.pos = pos # check code type, make code object for type, # or throw exception if not recognized if codetype == 'totp': self.code = TOTP(self.codestr) self.curcode = self.code.now() elif codetype == 'hotp': self.code = HOTP(self.codestr) self.curcode = self.code.at(self.counter) else: raise TypeError('codetype was not hotp or totp')
def get(request, pk): user = User.objects.get(pk=pk) user.verify_count += 1 user.save() keygen = generateKey() key = base64.b32encode(keygen.returnValue(user.phone).encode()) OTP = HOTP(key) try: res = send_mail( "Email verification", f'Dear {user.first_name}\n\n Please use this six digit code {OTP.at(user.verify_count)} to verify your account.\n Valid for 30sec.\n\n Thank you.', '*****@*****.**', [user.email], fail_silently=False, ) return Response({'message': f'Verification mail Sent to {user.email}'}, status.HTTP_200_OK) except BadHeaderError as e: return Response({'message': 'Invalid header found.'}, status.HTTP_400_BAD_REQUEST) except SMTPException as e: print(e) return Response({'message': 'Something Happened.'}, status.HTTP_500_INTERNAL_SERVER_ERROR)