def do_enroll(): devs = u2f.list_devices() req = make_reg_request() result = register.register(devs, req, OUR_APPID) # check client data from token clientData = json.loads(websafe_decode(result['clientData'])) assert clientData['origin'] == OUR_APPID assert clientData['challenge'] == req['challenge'] assert clientData['typ'] == 'navigator.id.finishEnrollment' # check registration data regData = decode_reg_response(websafe_decode(result['registrationData'])) salt = os.urandom(32) with open('data.json', 'w') as f: db = dict(hkey=websafe_encode(H(regData.pubkey)), keyhandle=websafe_encode(regData.keyhandle), salt=websafe_encode(salt)) json.dump(db, f) print 'written data to', f.name key = hashlib.pbkdf2_hmac('sha256', regData.pubkey + SOME_PASSWORD, salt, SOME_ITERATIONS) print 'secret is', key.encode('hex')
def main(): args = parse_args() facet = text_type(args.facet, sys.stdin.encoding or sys.getdefaultencoding()) if args.infile: with open(args.infile, 'r') as f: data = f.read() else: if sys.stdin.isatty(): sys.stderr.write('Enter RegistrationRequest JSON data...\n') data = sys.stdin.read() params = json.loads(data, object_hook=u2str) if args.soft: from u2flib_host.soft import SoftU2FDevice devices = [SoftU2FDevice(args.soft)] else: devices = u2f.list_devices() result = register(devices, params, facet) if args.outfile: with open(args.outfile, 'w') as f: json.dump(result, f) sys.stderr.write('Output written to %s\n' % args.outfile) else: sys.stderr.write('\n---Result---\n') print(json.dumps(result))
def do_auth(): devs = u2f.list_devices() db = json.load(open('data.json')) keyhandle = websafe_decode(db['keyhandle']) salt = websafe_decode(db['salt']) hkey = websafe_decode(db['hkey']) req = make_auth_request(keyhandle) result = authenticate.authenticate(devs, req, OUR_APPID, check_only = False) authData = decode_auth_response(websafe_decode(result['signatureData'])) open('sig.der', 'w').write(authData.sig) # decode our signature, and reconstruct the message that was signed sig = decode_sig(authData.sig) signed_message = H(req['appId']) + encode_auth_response_prefix(authData) + H(websafe_decode(result['clientData'])) # recover the two possible public keys from the signature pubkeys = ecdsa.recover_candidate_pubkeys(ec.nistp256, hashlib.sha256, signed_message, sig) pubkeys = [ec.nistp256.ec2osp(pk) for pk in pubkeys] if H(pubkeys[0]) == hkey: pubkey = pubkeys[0] elif H(pubkeys[1]) == hkey: pubkey = pubkeys[1] else: print 'token is broken/lying/replayed!' sys.exit(1) key = hashlib.pbkdf2_hmac('sha256', pubkey + SOME_PASSWORD, salt, SOME_ITERATIONS) print 'secret is', key.encode('hex')
def do_enroll(): devs = u2f.list_devices() req = make_reg_request() result = register.register(devs, req, OUR_APPID) # check client data from token clientData = json.loads(websafe_decode(result['clientData'])) assert clientData['origin'] == OUR_APPID assert clientData['challenge'] == req['challenge'] assert clientData['typ'] == 'navigator.id.finishEnrollment' # check registration data regData = decode_reg_response(websafe_decode(result['registrationData'])) salt = os.urandom(32) with open('data.json', 'w') as f: db = dict( hkey = websafe_encode(H(regData.pubkey)), keyhandle = websafe_encode(regData.keyhandle), salt = websafe_encode(salt) ) json.dump(db, f) print 'written data to', f.name key = hashlib.pbkdf2_hmac('sha256', regData.pubkey + SOME_PASSWORD, salt, SOME_ITERATIONS) print 'secret is', key.encode('hex')
def setTwoFactorMethod(self, user_dn, factor_method, user_password=None): if factor_method == "u2f": print(_("checking U2F devices...")) # check for devices devices = u2f.list_devices() if len(devices) == 0: print(_("No U2F devices found, aborting!")) return response = self.proxy.setTwoFactorMethod(user_dn, factor_method, user_password) if response is None: return if factor_method == "u2f": # bind response = loads(response) for device in devices: # The with block ensures that the device is opened and closed. print(_("Please touch the flashing U2F device now.")) with device as dev: # Register the device with some service for request in response['registerRequests']: registration_response = u2f.register(device, request, request['appId']) response = self.proxy.completeU2FRegistration(user_dn, registration_response) if response is True: print(_("U2F authentication has been enabled")) elif response.startswith("otpauth://"): url = pyqrcode.create(response, error='L') print(url.terminal(quiet_zone=1)) else: print(response)
def main(): args = parse_args() facet = text_type(args.facet) if args.infile: with open(args.infile, 'r') as f: data = f.read() else: if sys.stdin.isatty(): sys.stderr.write('Enter AuthenticateRequest JSON data...\n') data = sys.stdin.read() params = json.loads(data) if args.soft: from u2flib_host.soft import SoftU2FDevice devices = [SoftU2FDevice(args.soft)] else: devices = u2f.list_devices() result = authenticate(devices, params, facet, args.check_only) if args.outfile: with open(args.outfile, 'w') as f: json.dump(result, f) sys.stderr.write('Output written to %s\n' % args.outfile) else: sys.stderr.write('\n---Result---\n') print(json.dumps(result))
def get_u2f_devices(): """Get all U2F devices attached to the machine""" devices = u2f.list_devices() for device in devices: try: device.open() except: # pylint: disable=bare-except devices.remove(device) return devices
def getDevice(): devices = u2f.list_devices() if len(devices) != 1: sys.stderr.write('\nMore than one or no device detected. Exiting\n') sys.exit(1) device = None try: device = devices[0] device.open() except: pass return device
def main(): with u2f.list_devices()[0] as dev: dev.send_apdu(U2F_VENDOR_JUJU, INS_ERASE) with open('key.pem') as f: key = ecdsa.SigningKey.from_pem(f.read()) dev.send_apdu(U2F_VENDOR_JUJU, INS_SET_PRIVATE_KEY, data=key.to_string()) with open('cert.der', 'rb') as f: dev.send_apdu(U2F_VENDOR_JUJU, INS_SET_CERTIFICATE, data=f.read()) dev.send_apdu(U2F_VENDOR_JUJU, INS_SET_SEED, data=secrets.token_bytes(256))
def u2f_auth(challenges, facet): devices = u2f.list_devices() for device in devices[:]: try: device.open() except: # Some U2F devices fail on the first attempt to open but # succeed on subsequent attempts. So retry once. try: device.open() except: devices.remove(device) try: prompted = False while devices: removed = [] for device in devices: remove = True for challenge in challenges: try: return u2f.authenticate(device, json.dumps(challenge), facet) except exc.APDUError as e: if e.code == APDU_USE_NOT_SATISFIED: remove = False if not prompted: print('Touch the flashing U2F device to ' 'authenticate...') prompted = True else: pass except exc.DeviceError: pass if remove: removed.append(device) devices = [d for d in devices if d not in removed] for d in removed: d.close() time.sleep(0.25) finally: for device in devices: device.close() raise RuntimeWarning("U2F Device Not Found")
def okta_mfa_u2f(conf, s, factors, state_token): devices = u2f.list_devices() if not devices: err('no u2f devices found') return None for factor in factors: provider = factor.get('provider', '') log('mfa {0} challenge request'.format(provider)) r = s.post( factor.get('url'), headers=hdr_json(), data = json.dumps({ 'stateToken': state_token }) ) if r.status_code != 200: err('okta mfa challenge request failed. {0}'.format(reprr(r))) dbg(conf.get('debug'), 'challenge.response', r.status_code, r.text) j = parse_rjson(r) factor = j['_embedded']['factor'] profile = factor['profile'] auth_request_data = { 'appId': profile['appId'], 'keyHandle': profile['credentialId'], 'version': profile['version'], 'challenge': factor['_embedded']['challenge']['nonce'] } signed = do_u2f_sign(conf, devices, auth_request_data, profile['appId'], state_token) if signed: log('mfa {0} signed request'.format(provider)) r = s.post( j['_links']['next']['href'], headers=hdr_json(), data = json.dumps(signed) ) if r.status_code != 200: err('okta mfa signed request failed. {0}'.format(reprr(r))) dbg(conf.get('debug'), 'u2d.next.resp', r.status_code, r.text) j = parse_rjson(r) return j.get('sessionToken', '').strip() else: return None
def __handle_result(self, response): """ Handle the results of the different login steps (login, 2FA, U2F) and process with the next required step until the login process succeeds or fails. """ try: result_code = int(response['state']) if result_code == AUTH_FAILED: print(_("Login of user '%s' failed") % self.__username) sys.exit(1) elif result_code == AUTH_OTP_REQUIRED: key = input(_("OTP-Passkey: ")) return self.__handle_result(self.proxy.verify(key)) elif result_code == AUTH_U2F_REQUIRED and 'u2f_data' in response: for device in u2f.list_devices(): with device as dev: data = loads(response['u2f_data']) print(data) print(_("Please touch the flashing U2F device now.")) for request in data['authenticateRequests']: data = u2f.authenticate(device, request, request['appId']) res = self.proxy.verify(data) if 'counter' in res and 'touch' in res: return True return False elif result_code == AUTH_SUCCESS: return True except Exception as e: print(e) sys.exit(1) return False
def do_auth(): devs = u2f.list_devices() db = json.load(open('data.json')) keyhandle = websafe_decode(db['keyhandle']) salt = websafe_decode(db['salt']) hkey = websafe_decode(db['hkey']) req = make_auth_request(keyhandle) result = authenticate.authenticate(devs, req, OUR_APPID, check_only=False) authData = decode_auth_response(websafe_decode(result['signatureData'])) open('sig.der', 'w').write(authData.sig) # decode our signature, and reconstruct the message that was signed sig = decode_sig(authData.sig) signed_message = H( req['appId']) + encode_auth_response_prefix(authData) + H( websafe_decode(result['clientData'])) # recover the two possible public keys from the signature pubkeys = ecdsa.recover_candidate_pubkeys(ec.nistp256, hashlib.sha256, signed_message, sig) pubkeys = [ec.nistp256.ec2osp(pk) for pk in pubkeys] if H(pubkeys[0]) == hkey: pubkey = pubkeys[0] elif H(pubkeys[1]) == hkey: pubkey = pubkeys[1] else: print 'token is broken/lying/replayed!' sys.exit(1) key = hashlib.pbkdf2_hmac('sha256', pubkey + SOME_PASSWORD, salt, SOME_ITERATIONS) print 'secret is', key.encode('hex')
def __handle_result(self, response): """ Handle the results of the different login steps (login, 2FA, U2F) and process with the next required step until the login process succeeds or fails. """ try: print(response) result_code = int(response['state']) if result_code == AUTH_FAILED: print(_("Login of user '%s' failed") % self.__username) sys.exit(1) elif result_code == AUTH_OTP_REQUIRED: key = input(_("OTP-Passkey: ")) return self.__handle_result(self.proxy.verify(key)) elif result_code == AUTH_U2F_REQUIRED and 'u2f_data' in response: for device in u2f.list_devices(): with device as dev: data = loads(response['u2f_data']) print(data) print(_("Please touch the flashing U2F device now.")) for request in data['authenticateRequests']: data = u2f.authenticate(device, request, request['appId']) res = self.proxy.verify(data) if 'counter' in res and 'touch' in res: return True return False elif result_code == AUTH_SUCCESS: return True except Exception as e: print(e) sys.exit(1) return False
import sys import requests import json facet = 'http://localhost:8081' if 1: try: registrationRequest = json.loads( requests.get("http://localhost:8081/enroll").text) print registrationRequest registrationRequest = registrationRequest['registerRequests'][0] # Enumerate available devices devices = u2f.list_devices() for device in devices: # The with block ensures that the device is opened and closed. with device as dev: # Register the device with some service print 'Reg: press button . . .' sys.stdout.flush() registrationResponse = u2f.register(device, registrationRequest, facet) print registrationResponse registrationResponse['version'] = 'U2F_V2' bindres = (requests.post("http://localhost:8081/bind", data={ 'data': json.dumps(registrationResponse)
def _verify_single_factor(self, factor): """ Verifies a single MFA factor """ req_data = { "stateToken": self.state_token } self.logger.debug(factor) if factor['factorType'] == 'token:software:totp': if self.totp_token: self.logger.debug("Using TOTP token from command line arg") req_data['answer'] = self.totp_token else: req_data['answer'] = input('Enter MFA verification code: ') post_url = factor['_links']['verify']['href'] resp = requests.post(post_url, json=req_data) resp_json = resp.json() if 'status' in resp_json: if resp_json['status'] == "SUCCESS": return resp_json['sessionToken'] elif resp_json['status'] == "MFA_CHALLENGE" and factor['factorType'] !='u2f': print("Waiting for push verification...") while True: resp = requests.post( resp_json['_links']['next']['href'], json=req_data) resp_json = resp.json() if resp_json['status'] == 'SUCCESS': return resp_json['sessionToken'] elif resp_json['factorResult'] == 'TIMEOUT': print("Verification timed out") sys.exit(1) elif resp_json['factorResult'] == 'REJECTED': print("Verification was rejected") sys.exit(1) else: time.sleep(0.5) if factor['factorType'] == 'u2f': devices = u2f.list_devices() if len(devices) == 0: self.logger.warning("No U2F device found") sys.exit(1) challenge = dict() challenge['appId'] = resp_json['_embedded']['factor']['profile']['appId'] challenge['version'] = resp_json['_embedded']['factor']['profile']['version'] challenge['keyHandle'] = resp_json['_embedded']['factor']['profile']['credentialId'] challenge['challenge'] = resp_json['_embedded']['factor']['_embedded']['challenge']['nonce'] print("Please touch your U2F device...") auth_response = None while not auth_response: for device in devices: with device as dev: try: auth_response = u2f.authenticate(dev, challenge, resp_json['_embedded']['factor']['profile']['appId'] ) req_data.update(auth_response) resp = requests.post(resp_json['_links']['next']['href'], json=req_data) resp_json = resp.json() if resp_json['status'] == 'SUCCESS': return resp_json['sessionToken'] elif resp_json['factorResult'] == 'TIMEOUT': self.logger.warning("Verification timed out") sys.exit(1) elif resp_json['factorResult'] == 'REJECTED': self.logger.warning("Verification was rejected") sys.exit(1) except exc.APDUError as ex: if ex.code == APDU_WRONG_DATA: devices.remove(device) time.sleep(0.1) elif resp.status_code != 200: self.logger.error(resp_json['errorSummary']) sys.exit(1) else: self.logger.error(resp_json) sys.exit(1) return None
def u2freq(ins, p1, p2, msg): with u2f.list_devices()[0] as d: return d.send_apdu(ins, p1, p2, msg)