def sync_token(token, secret, session=requests, timestamp=None): '''Sync the generated token. This will fail for a TOTP token if performed less than 2 periods after the last sync or check.''' secret_hex = binascii.b2a_hex(secret).decode('ascii') if timestamp is None: timestamp = int(time.time()) if token.get('counter') is not None: # HOTP # This reliably fails with -1, 0 otp1 = hotp(secret_hex, counter=token['counter']) otp2 = hotp(secret_hex, counter=token['counter'] + 1) elif token.get('period'): # TOTP otp1 = totp(secret_hex, period=token['period'], t=timestamp - token['period']) otp2 = totp(secret_hex, period=token['period'], t=timestamp) else: # Assume TOTP with default period 30 (FIXME) otp1 = totp(secret_hex, t=timestamp - 30) otp2 = totp(secret_hex, t=timestamp) data = {'cr%s' % d: c for d, c in enumerate(otp1, 1)} data.update({'ncr%s' % d: c for d, c in enumerate(otp2, 1)}) data['cred'] = token['id'] data['continue'] = 'otp_sync' token_check = session.post(SYNC_URL, data=data) if "Your VIP Credential is successfully synced" in token_check.text: if token.get('counter') is not None: token['counter'] += 2 return True elif "Your VIP credential needs to be sync" in token_check.text: return False else: return None
def check_token(token_id, secret, session=requests): '''Check the validity of the generated token.''' test_url = 'https://vip.symantec.com/otpCheck' if token_id.startswith('VSMB'): print('Checking HOTP token with Counter=1') otp = hotp(binascii.b2a_hex(secret), 1).decode('utf-8') else: print('Checking TOTP token with Current Time') otp = totp(binascii.b2a_hex(secret).decode('utf-8')) token_check = session.post(test_url, data={ 'cr1': otp[0], 'cr2': otp[1], 'cr3': otp[2], 'cr4': otp[3], 'cr5': otp[4], 'cr6': otp[5], 'cred': token_id, 'count': '1', 'continue': 'otp_check' }) if "Your VIP Credential is working correctly" in token_check.text: return True elif "Your VIP credential needs to be sync" in token_check.text: return False else: return None
def get_access_token(): """Generate an OTP access token from .vipaccess configuration in your home dir""" info("Generating Token") dotfile=os.path.expanduser('~/.vipaccess') if os.path.exists(dotfile) is False: raise Exception("vipaccess not configured. No token can be created") with open(dotfile, "r") as dotfile: d = dict( l.strip().split(None, 1) for l in dotfile ) if 'version' not in d: raise Exception('%s does not specify version' % dotfile) elif d['version'] != '1': raise Exception("%s specifies version %r, rather than expected '1'" % (dotfile, d['version'])) elif 'secret' not in d: raise Exception('%s does not specify secret' % dotfile) secret = d.get('secret') try: key = oath._utils.tohex( oath.google_authenticator.lenient_b32decode(secret) ) token=oath.totp(key) return token except Exception as e: raise Exception('error interpreting secret as base32: %s' % e)
def show(p, args): if args.secret: secret = args.secret else: with open(args.dotfile, "r") as dotfile: d = dict(l.strip().split(None, 1) for l in dotfile) if 'version' not in d: p.error('%s does not specify version' % args.dotfile) elif d['version'] != '1': p.error("%s specifies version %r, rather than expected '1'" % (args.dotfile, d['version'])) elif 'secret' not in d: p.error('%s does not specify secret' % args.dotfile) secret = d.get('secret') if args.verbose: if 'id' in d: print('Token ID: %s' % d['id'], file=sys.stderr) if 'expiry' in d: print('Token expiration: %s' % d['expiry'], file=sys.stderr) sys.stderr.write('\n') try: key = oath._utils.tohex( oath.google_authenticator.lenient_b32decode(secret)) except Exception as e: p.error('error interpreting secret as base32: %s' % e) print(oath.totp(key))
def setUp(self): self.user = User.objects.create_user( username="******", password="******") UserAuthToken.objects.create( user=self.user, encrypted_seed=encrypt_value("s33d"), type=UserAuthToken.TYPE_TOTP) self.correct_code = totp(hexlify("s33d"))
def check_token(token_id, secret): '''Check the validity of the generated token.''' if token_id.startswith('VSMB'): otp = hotp(binascii.b2a_hex(secret),1).encode('utf-8') else: otp = totp(binascii.b2a_hex(secret)).encode('utf-8') test_url = 'https://idprotect.vip.symantec.com/otpCheck' token_check = requests.post( test_url, data=dict( cred=token_id, cr1=otp[0], cr2=otp[1], cr3=otp[2], cr4=otp[3], cr5=otp[4], cr6=otp[5], cr7="", count="1", ) ) if token_check.status_code != 200: sys.stderr.write("Bad token check url, " + token_check.status_code + "\n") return True if "Your VIP Credential is working correctly" in token_check.text: return True else: sys.stderr.write("bad otp \"" + otp + "\" : " + token_check.text + "\n") return False
def setUp(self): self.user = User.objects.create_user(username="******", password="******") UserAuthToken.objects.create(user=self.user, encrypted_seed=encrypt_value("s33d"), type=UserAuthToken.TYPE_TOTP) self.correct_code = totp(hexlify("s33d"))
def _valid_code(seed, drift=0): """Generate a valid code. :param drift: Number of periods to drift from current time. Optional. :return: valid 6-character two-factor response :rtype: str """ return totp(key=seed, t=int(time.time()) + (drift * 30))
def show(p, args): if args.secret: key = oath._utils.tohex( oath.google_authenticator.lenient_b32decode(args.secret) ) else: with open(args.dotfile, "r") as dotfile: d = dict( l.strip().split(None, 1) for l in dotfile ) assert d.get('version')=='1' key = oath._utils.tohex( oath.google_authenticator.lenient_b32decode(d.get('secret')) ) print(oath.totp(key))
def getOTT(self): request = vipaccess.generate_request() response = requests.post(vipaccess.PROVISIONING_URL, data=request) otp_token = vipaccess.get_token_from_response(response.content) otp_secret = vipaccess.decrypt_key(otp_token['iv'], otp_token['cipher']) if not vipaccess.check_token(otp_token['id'], otp_secret): sys.stderr.write("Something went wrong--the token is invalid.\n") sys.exit(1) otp = oath.totp(binascii.b2a_hex(otp_secret)) return otp
def check_token(token_id, secret): '''Check the validity of the generated token.''' otp = totp(binascii.b2a_hex(secret).decode('utf-8')) test_url = 'https://idprotect.vip.symantec.com/testtoken.v' token_check = requests.post(test_url, data=dict(tokenID=token_id, firstOTP=otp)) if "Your credential is functioning properly and is ready for use" in token_check.text: return True else: return False
def _valid_code(seed, drift=0): """Generate a valid code. :param drift: Number of periods to drift from current time. Optional. :return: valid 6-character two-factor response :rtype: str """ return totp( key=seed, t=int(time.time()) + (drift * 30) )
def check_token(token, secret, session=requests): '''Check the validity of the generated token.''' secret_b32 = binascii.b2a_hex(secret).decode('ascii') if token.get('counter') is not None: # HOTP otp = hotp(secret_b32, counter=token['counter']) elif token.get('period'): # TOTP otp = totp(secret_b32, period=token['period']) else: # Assume TOTP with default period 30 (FIXME) otp = totp(secret_b32) data = {'cr%s'%d:c for d,c in enumerate(otp, 1)} data['cred'] = token['id'] data['continue'] = 'otp_check' token_check = session.post(TEST_URL, data=data) if "Your VIP Credential is working correctly" in token_check.text: if token.get('counter') is not None: token['counter'] += 1 return True elif "Your VIP credential needs to be sync" in token_check.text: return False else: return None
def get_digits(self): if self._token != None: secret = self.__decrypt_key(self._token['iv'], self._token['cipher']) secret_b32 = base64.b32encode(secret).upper().decode('ascii') print("secret is " + secret_b32) key = oath._utils.tohex( oath.google_authenticator.lenient_b32decode(secret_b32)) self._key = oath.totp(key) return True return False
def render_next_step(self, form, **kwargs): response = super(Enable, self).render_next_step(form, **kwargs) if self.steps.current in ['call-verify', 'sms-verify']: method = self.get_form_data('method', 'method') #todo use backup phone #todo resend message + throttling generated_token = totp(self.get_token_seed()) if method == 'call': phone = self.get_form_data('call', 'phone') call(to=phone, request=self.request, token=generated_token) elif method == 'sms': phone = self.get_form_data('sms', 'phone') send(to=phone, request=self.request, token=generated_token) return response
def check_token(token_id, secret): '''Check the validity of the generated token.''' otp = totp(binascii.b2a_hex(secret).decode('utf-8')) test_url = 'https://idprotect.vip.symantec.com/testtoken.v' token_check = requests.post( test_url, data=dict( tokenID=token_id, firstOTP=otp ) ) if "Your credential is functioning properly and is ready for use" in token_check.text: return True else: return False
def check_token(token_id, secret): '''Check the validity of the generated token.''' otp = totp(binascii.b2a_hex(secret).decode('utf-8')) test_url = 'https://vip.symantec.com/otpCheck' token_check = requests.post(test_url, data={ 'cr1': otp[0], 'cr2': otp[1], 'cr3': otp[2], 'cr4': otp[3], 'cr5': otp[4], 'cr6': otp[5], 'cred': token_id, 'continue': 'otp_check' }) if "Your VIP Credential is working correctly" in token_check.text: return True else: return False
def check_token(token_id, secret): '''Check the validity of the generated token.''' otp = totp(binascii.b2a_hex(secret).decode('utf-8')) test_url = 'https://vip.symantec.com/otpCheck' token_check = requests.post( test_url, data={ 'cr1': otp[0], 'cr2': otp[1], 'cr3': otp[2], 'cr4': otp[3], 'cr5': otp[4], 'cr6': otp[5], 'cred': token_id, 'continue': 'otp_check' } ) if "Your VIP Credential is working correctly" in token_check.text: return True else: return False
def get(self, request, *args, **kwargs): sms_password_recovery = (self.request.localconfig.parameters.get_value( "sms_password_recovery")) if not sms_password_recovery: raise Http404 try: user = models.User._default_manager.get( pk=self.request.session["user_pk"]) except KeyError: raise Http404 backend = sms_backends.get_active_backend( self.request.localconfig.parameters) secret = cryptutils.random_hex_key(20) code = oath.totp(secret) text = _( "Please use the following code to recover your Modoboa password: {}" .format(code)) if not backend.send(text, [user.phone_number]): raise Http404 self.request.session["totp_secret"] = secret return JsonResponse({"status": "ok"})
def connect(conn_config_dict): ''' Test the status of AnyConnect and connect to VPN if the status==Disconnected ''' if 'VPNCLI_PATH' not in conn_config_dict or 'VPN_URL' not in conn_config_dict or 'USER_NAME' not in conn_config_dict or 'PASS_WD' not in conn_config_dict or 'TOKEN_KEY' not in conn_config_dict: print 'Invalid configure file' return state_pattern = re.compile(r'Disconnected|Connected') VPNCLI_PATH = conn_config_dict['VPNCLI_PATH'] USER_NAME = conn_config_dict['USER_NAME'] PASS_WD = conn_config_dict['PASS_WD'] VPN_URL = conn_config_dict['VPN_URL'] TOKEN_KEY = conn_config_dict['TOKEN_KEY'] st_output = Popen([VPNCLI_PATH, '-s'], stdin=PIPE, stdout=PIPE).communicate(os.linesep.join(['state']))[0] st_output = st_output.replace('\r', '') st_set = set(state_pattern.findall(st_output)) conn_status = 'Disconnected' if not st_set and len(st_set) > 1: ### exit in case have more than one status, which means there is some issues with extract status code print st_output return False elif len(st_set) == 1: conn_status = st_set.pop() if conn_status == 'Disconnected': proc = Popen([VPNCLI_PATH, '-s'], stdin=PIPE, stdout=None) proc.communicate( os.linesep.join([ 'connect %s' % (VPN_URL), USER_NAME, PASS_WD, oath.totp(TOKEN_KEY), 'y' ])) elif conn_status == 'Connected': #print st_output proc = Popen([VPNCLI_PATH, '-s'], stdin=PIPE, stdout=None) proc.communicate(os.linesep.join(['disconnect']))
def show(secrets): output = "" output_list = [] for entry in secrets: decrypted_key = entry['key'] if len(decrypted_key) < 16: decrypted_key = decrypted_key + '=' * (16-len(decrypted_key)) elif len(decrypted_key) < 32 and len(decrypted_key) != 16: decrypted_key = decrypted_key + '=' * (32-len(decrypted_key)) secret = base64.b32decode(decrypted_key).encode('hex') output_list.append([entry['provider'], entry['label'], totp(secret)]) output_list = sorted(output_list, key=itemgetter(0, 1)) output += tabulate(output_list, ['Provider', 'Label', 'TOTP']) output += "\n" output += "\n" output += "Control-C to exit." screen.addstr(3, 0, output) screen.refresh()
def form_valid(self, form): """Redirect to code verification page if needed.""" sms_password_recovery = (self.request.localconfig.parameters.get_value( "sms_password_recovery")) if not sms_password_recovery: return super().form_valid(form) user = models.User._default_manager.filter( email=form.cleaned_data["email"], phone_number__isnull=False).first() if not user: # Fallback to email return super().form_valid(form) backend = sms_backends.get_active_backend( self.request.localconfig.parameters) secret = cryptutils.random_hex_key(20) code = oath.totp(secret) text = _( "Please use the following code to recover your Modoboa password: {}" .format(code)) if not backend.send(text, [str(user.phone_number)]): return super().form_valid(form) self.request.session["user_pk"] = user.pk self.request.session["totp_secret"] = secret return HttpResponseRedirect(reverse("password_reset_confirm_code"))
#!/usr/bin/env python import oath secret = "NFZXI2DJON2GQZLSMVQWY3DJMZSQU===" a = oath._utils.tohex(oath.google_authenticator.lenient_b32decode(secret)) print oath.totp(a)
def calculate_key(self, secret_b32): key = oath._utils.tohex( oath.google_authenticator.lenient_b32decode(secret_b32)) return oath.totp(key)
def generateOTPValue(seed): """Generate OTP value from given seed.""" if type(seed) is not str: raise TypeError("Argument seed needs to be str") return totp(_generateKey(seed), period=60)
def verify_computer(request, template_name='two_factor/verify_computer.html', redirect_field_name=REDIRECT_FIELD_NAME, computer_verification_form=ComputerVerificationForm, current_app=None, extra_context=None): redirect_to = request.REQUEST.get(redirect_field_name, '') netloc = urlparse.urlparse(redirect_to)[1] # Use default setting if redirect_to is empty if not redirect_to: redirect_to = settings.LOGIN_REDIRECT_URL # Heavier security check -- don't allow redirection to a different # host. elif netloc and netloc != request.get_host(): redirect_to = settings.LOGIN_REDIRECT_URL try: user = User.objects.get(pk=request.session.get('tf_user', None)) except User.DoesNotExist: return HttpResponseRedirect(settings.LOGIN_URL) if request.method == 'POST': form = computer_verification_form(user=user, data=request.POST) if form.is_valid(): # Okay, security checks complete. Log the user in. auth_login(request, user) if request.session.test_cookie_worked(): request.session.delete_test_cookie() response = HttpResponseRedirect(redirect_to) # set computer verification if form.cleaned_data['remember']: vf = user.verifiedcomputer_set.create( verified_until=now() + timedelta(days=30), last_used_at=now(), ip=request.META['REMOTE_ADDR']) response.set_signed_cookie('computer', vf.id, path=reverse('tf:verify'), max_age=30*86400, httponly=True) return response else: form = computer_verification_form(request, user) # has this computer been verified? try: computer_id = request.get_signed_cookie('computer', None) user = authenticate(user=user, computer_id=computer_id) if user and user.is_active: # Okay, security checks complete. Log the user in. auth_login(request, user) if request.session.test_cookie_worked(): request.session.delete_test_cookie() return HttpResponseRedirect(redirect_to) except VerifiedComputer.DoesNotExist: pass token = user.token if token.method in ('call', 'sms'): #todo use backup phone #todo resend message + throttling generated_token = totp(token.seed) if token.method == 'call': call(to=token.phone, request=request, token=generated_token) elif token.method == 'sms': send(to=token.phone, request=request, token=generated_token) current_site = get_current_site(request) context = { 'form': form, redirect_field_name: redirect_to, 'site': current_site, 'site_name': current_site.name, } if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context, current_app=current_app)
def get_totp(period=180): totp = oath.totp(os.environ.get('OTP_SECRET_KEY'), format='dec6', period=period) return totp
if args.policy is not None: password += args.policy[0].encode('utf-8') logging.info("Policy: %s", args.policy[0].encode('utf-8')) else: logging.debug("Policy not provided") # Derive the secret key key = pbkdf2_hmac(hash_name='sha256', password=password, salt=serial.encode("utf-8"), iterations=8, dklen=16) # Verify whether the output is valid for the given time otp = totp(key.hex(), hash=hashlib.sha256, t=otpTime, format=digitformat) if otp == args.OTP[0]: print("Possibe valid OTP seed found: ", key.hex()) keys.append(key) if len(keys) == 0: print("No valid keys were found") elif len(keys) == 1: print("To generate a code immediately, run:") print("oathtool -v --totp=sha256 --digits=6 " + keys[0].hex()) else: print("To generate a code immediately, run:") print("oathtool -v --totp=sha256 --digits=6 (found key)")
def create(seed, hash=hashlib.sha512): """Create a new TOTP for the given secret seed and hash, using the default 30 second time step period.""" return totp(stringToHex(seed), format='dec8', hash=hash)
if args.policy is not None: password += args.policy[0].encode('utf-8') logging.info("Policy: %s", args.policy[0].encode('utf-8')) else: logging.debug("Policy not provided") # Derive the secret key key = pbkdf2_hmac( hash_name='sha256', password=password, salt=serial.encode("utf-8"), iterations=8, dklen=16 ) # Verify whether the output is valid for the given time otp = totp(key.hex(), hash=hashlib.sha256, t=otpTime) if otp == args.OTP[0]: print("Possibe valid OTP seed found: ", key.hex()) keys.append(key) if len(keys) == 0: print("No valid keys were found") elif len(keys) == 1: print("To generate a code immediately, run:") print("oathtool -v --totp=sha256 --digits=6 " + keys[0].hex()) else: print("To generate a code immediately, run:") print("oathtool -v --totp=sha256 --digits=6 (found key)")
def generate_totp(period=3600): totp = oath.totp(OTP_SECRET_KEY, format='dec6', period=period) return totp