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 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 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 test_register(self): device = MockDevice(DUMMY_RESP) response = u2f_v2.register(device, REG_DATA, FACET) self.assertEqual(device.ins, INS_ENROLL) self.assertEqual(device.p1, 0x03) self.assertEqual(device.p2, 0x00) self.assertEqual(len(device.request), 64) self.assertEqual(websafe_decode(response['registrationData']), DUMMY_RESP) client_data = json.loads( websafe_decode(response['clientData']).decode('utf8')) self.assertEqual(client_data['typ'], 'navigator.id.finishEnrollment') self.assertEqual(client_data['origin'], FACET) self.assertEqual(client_data['challenge'], CHALLENGE)
def test_register(self): device = MockDevice(DUMMY_RESP) response = u2f_v2.register(device, REG_DATA, FACET) self.assertEqual(device.ins, INS_ENROLL) self.assertEqual(device.p1, 0x03) self.assertEqual(device.p2, 0x00) self.assertEqual(len(device.request), 64) self.assertEqual(websafe_decode(response['registrationData']), DUMMY_RESP) client_data = json.loads(websafe_decode(response['clientData']) .decode('utf8')) self.assertEqual(client_data['typ'], 'navigator.id.finishEnrollment') self.assertEqual(client_data['origin'], FACET) self.assertEqual(client_data['challenge'], CHALLENGE)
def test_authenticate(self): device = MockDevice(DUMMY_RESP) response = u2f_v2.authenticate(device, AUTH_DATA, FACET, False) self.assertEqual(device.ins, INS_SIGN) self.assertEqual(device.p1, 0x03) self.assertEqual(device.p2, 0x00) self.assertEqual(len(device.request), 64 + 1 + 64) self.assertEqual(device.request[-64:], websafe_decode(KEY_HANDLE)) self.assertEqual(response['keyHandle'], KEY_HANDLE) self.assertEqual(websafe_decode(response['signatureData']), DUMMY_RESP) client_data = json.loads( websafe_decode(response['clientData']).decode('utf8')) self.assertEqual(client_data['typ'], 'navigator.id.getAssertion') self.assertEqual(client_data['origin'], FACET) self.assertEqual(client_data['challenge'], CHALLENGE)
def test_authenticate(self): device = MockDevice(DUMMY_RESP) response = u2f_v2.authenticate(device, AUTH_DATA, FACET, False) self.assertEqual(device.ins, INS_SIGN) self.assertEqual(device.p1, 0x03) self.assertEqual(device.p2, 0x00) self.assertEqual(len(device.request), 64 + 1 + 64) self.assertEqual(device.request[-64:], websafe_decode(KEY_HANDLE)) self.assertEqual(response['keyHandle'], KEY_HANDLE) self.assertEqual(websafe_decode(response['signatureData']), DUMMY_RESP) client_data = json.loads(websafe_decode(response['clientData']) .decode('utf8')) self.assertEqual(client_data['typ'], 'navigator.id.getAssertion') self.assertEqual(client_data['origin'], FACET) self.assertEqual(client_data['challenge'], CHALLENGE)
def test_websafe_decode(self): self.assertEqual(websafe_decode(''), '') self.assertEqual(websafe_decode('Zg'), 'f') self.assertEqual(websafe_decode('Zm8'), 'fo') self.assertEqual(websafe_decode('Zm9v'), 'foo') self.assertEqual(websafe_decode('Zm9vYg'), 'foob') self.assertEqual(websafe_decode('Zm9vYmE'), 'fooba') self.assertEqual(websafe_decode('Zm9vYmFy'), 'foobar')
def test_websafe_decode(self): self.assertEqual(websafe_decode(b''), b'') self.assertEqual(websafe_decode(b'Zg'), b'f') self.assertEqual(websafe_decode(b'Zm8'), b'fo') self.assertEqual(websafe_decode(b'Zm9v'), b'foo') self.assertEqual(websafe_decode(b'Zm9vYg'), b'foob') self.assertEqual(websafe_decode(b'Zm9vYmE'), b'fooba') self.assertEqual(websafe_decode(b'Zm9vYmFy'), b'foobar')
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 authenticate(device, data, facet, check_only=False): """ Signs an authentication challenge data = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle) } """ if isinstance(data, basestring): data = json.loads(data) if data['version'] != VERSION: raise ValueError('Unsupported U2F version: %s' % data['version']) app_id = data.get('appId', facet) verify_facet(app_id, facet) app_param = H(app_id) key_handle = websafe_decode(data['keyHandle']) # Client data client_data = { 'typ': 'navigator.id.getAssertion', 'challenge': data['challenge'], 'origin': facet } client_data = json.dumps(client_data) client_param = H(client_data) request = client_param + app_param + chr( len(key_handle)) + key_handle p1 = 0x07 if check_only else 0x03 p2 = 0 response = device.send_apdu(INS_SIGN, p1, p2, request) return { 'clientData': websafe_encode(client_data), 'signatureData': websafe_encode(response), 'keyHandle': data['keyHandle'] }
def authenticate(device, data, facet, check_only=False): """ Signs an authentication challenge data = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle) } """ if isinstance(data, basestring): data = json.loads(data) if data['version'] != VERSION: raise ValueError('Unsupported U2F version: %s' % data['version']) app_id = data.get('appId', facet) verify_facet(app_id, facet) app_param = H(app_id) key_handle = websafe_decode(data['keyHandle']) # Client data client_data = { 'typ': 'navigator.id.getAssertion', 'challenge': data['challenge'], 'origin': facet } client_data = json.dumps(client_data) client_param = H(client_data) request = client_param + app_param + chr(len(key_handle)) + key_handle p1 = 0x07 if check_only else 0x03 p2 = 0 response = device.send_apdu(INS_SIGN, p1, p2, request) return { 'clientData': websafe_encode(client_data), 'signatureData': websafe_encode(response), 'keyHandle': data['keyHandle'] }
def test_websafe_decode_unicode(self): self.assertEqual(websafe_decode(u''), b'') self.assertEqual(websafe_decode(u'Zm9vYmFy'), b'foobar')