def data(self): """Return a SignRequest.""" return SignRequest( version=VERSION, challenge=websafe_encode(self.challenge), keyHandle=websafe_encode(self.binding.key_handle), appId=self.binding.app_id )
def register(self, facet, app_id, request): """ RegisterRequest = { "version": "U2F_V2", "challenge": string, //b64 encoded challenge "appId": string, //app_id } """ if not isinstance(request, RegisterRequest): request = RegisterRequest(request) if request.version != 'U2F_V2': raise ValueError('Unsupported U2F version: %s' % request.version) # Client data client_data = ClientData( typ=Type.REGISTER.value, challenge=request['challenge'], origin=facet ) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # ECC key generation priv_key = ec.generate_private_key(CURVE, default_backend()) pub_key = priv_key.public_key().public_bytes( Encoding.DER, PublicFormat.SubjectPublicKeyInfo) pub_key = pub_key[-65:] # Store key_handle = os.urandom(64) app_param = sha_256(app_id.encode('idna')) self.keys[key_handle] = (priv_key, app_param) # Attestation signature cert_priv = load_pem_private_key( CERT_PRIV, password=None, backend=default_backend()) cert = CERT data = b'\x00' + app_param + client_param + key_handle + pub_key signer = cert_priv.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = (b'\x05' + pub_key + six.int2byte(len(key_handle)) + key_handle + cert + signature) return RegisterResponse( version=request.version, registrationData=websafe_encode(raw_response), clientData=websafe_encode(client_data), )
def register(self, facet, app_id, request): """ RegisterRequest = { "version": "U2F_V2", "challenge": string, //b64 encoded challenge "appId": string, //app_id } """ if not isinstance(request, RegisterRequest): request = RegisterRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) # Client data client_data = ClientData(typ=Type.REGISTER.value, challenge=request['challenge'], origin=facet) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # ECC key generation priv_key = ec.generate_private_key(CURVE, default_backend()) pub_key = priv_key.public_key().public_bytes( Encoding.DER, PublicFormat.SubjectPublicKeyInfo) pub_key = pub_key[-65:] # Store key_handle = os.urandom(64) app_param = sha_256(app_id.encode('idna')) self.keys[key_handle] = (priv_key, app_param) # Attestation signature cert_priv = load_pem_private_key(CERT_PRIV, password=None, backend=default_backend()) cert = CERT data = b'\x00' + app_param + client_param + key_handle + pub_key signer = cert_priv.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = (b'\x05' + pub_key + six.int2byte(len(key_handle)) + key_handle + cert + signature) return RegisterResponse( version=request.version, registrationData=websafe_encode(raw_response), clientData=websafe_encode(client_data), )
def getAssertion(self, request, facet="https://www.example.com", touch=False): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData( typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet ) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # Unwrap: priv_key, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = int2byte(1 if touch else 0) counter = struct.pack('>I', self.counter) data = app_param + touch + counter + client_param signer = priv_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = touch + counter + signature return SignResponse( clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle )
def register( self, data, facet="https://www.example.com", ): """ data = { "version": "U2F_V2", "challenge": string, //b64 encoded challenge "appId": string, //app_id } """ if isinstance(data, basestring): data = json.loads(data) if data['version'] != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % data['version']) # Client data client_data = { 'typ': "navigator.id.finishEnrollment", 'challenge': data['challenge'], 'origin': facet } client_data = json.dumps(client_data) client_param = H(client_data) # ECC key generation privu = EC.gen_params(CURVE) privu.gen_key() pub_key = str(privu.pub().get_der())[-65:] # Store key_handle = rand_bytes(64) app_param = H(data['appId']) self.keys[key_handle] = (privu, app_param) # Attestation signature cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV)) cert = CERT digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key) signature = cert_priv.sign_dsa_asn1(digest) raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \ key_handle + cert + signature return json.dumps({ "registrationData": websafe_encode(raw_response), "clientData": websafe_encode(client_data), })
def getAssertion(self, request, facet="https://www.example.com"): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData( typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet ) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # Unwrap: priv_key, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = int2byte(1) counter = struct.pack('>I', self.counter) data = app_param + touch + counter + client_param signer = priv_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = touch + counter + signature return SignResponse( clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle )
def register(self, request, facet="https://www.example.com"): """ RegisterRequest = { "version": "U2F_V2", "challenge": string, //b64 encoded challenge "appId": string, //app_id } """ if not isinstance(request, RegisterRequest): request = RegisterRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) # Client data client_data = ClientData( typ='navigator.id.finishEnrollment', challenge=request['challenge'], origin=facet ) client_data = client_data.json client_param = H(client_data) # ECC key generation priv_key = ec.generate_private_key(CURVE, default_backend()) pub_key = priv_key.public_key().public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo) pub_key = str(pub_key)[-65:] # Store key_handle = rand_bytes(64) app_param = request.appParam self.keys[key_handle] = (priv_key, app_param) # Attestation signature cert_priv = load_pem_private_key(CERT_PRIV, password=None, backend=default_backend()) cert = CERT digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key) signer = cert_priv.signer(ec.ECDSA(hashes.SHA256())) signer.update(digest) signature = signer.finalize() raw_response = (chr(0x05) + pub_key + chr(len(key_handle)) + key_handle + cert + signature) return RegisterResponse( registrationData=websafe_encode(raw_response), clientData=websafe_encode(client_data), )
def getAssertion(self, facet, app_id, challenge, key, touch_byte=1): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ key = RegisteredKey.wrap(key) if key.version != 'U2F_V2': raise ValueError('Unsupported U2F version: %s' % key.version) if key.keyHandle not in self.keys: raise ValueError('Unknown key handle!') # Client data client_data = ClientData( typ=Type.SIGN.value, challenge=challenge, origin=facet ) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # Unwrap: priv_key, app_param = self.keys[key.keyHandle] # Increment counter self.counter += 1 # Create signature touch = six.int2byte(touch_byte) counter = struct.pack('>I', self.counter) data = app_param + touch + counter + client_param signer = priv_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = touch + counter + signature return SignResponse( clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=key['keyHandle'] )
def getAssertion(self, request, facet="https://www.example.com", touch=False): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData( typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet ) client_data = client_data.json client_param = H(client_data) # Unwrap: privu, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = chr(1 if touch else 0) counter = struct.pack('>I', self.counter) digest = H(app_param + touch + counter + client_param) signature = privu.sign_dsa_asn1(digest) raw_response = touch + counter + signature return SignResponse( clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle )
def start_register(app_id, challenge=None): if challenge is None: challenge = rand_bytes(32) return RegisterRequest(version=VERSION, appId=app_id, challenge=websafe_encode(challenge))
def data(self): """Return a RegisterRequest object.""" return RegisterRequest( version=VERSION, challenge=websafe_encode(self.challenge), appId=self.app_id )
def create(cls, app_id, devices, challenge=None): if challenge is None: challenge = os.urandom(32) return cls(appId=app_id, registeredKeys=devices, challenge=websafe_encode(challenge))
def getAssertion(self, data, facet="https://www.example.com", touch=False): """ signData = { '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'] != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % data['version']) key_handle = websafe_decode(data['keyHandle']) if not key_handle in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = { 'typ': "navigator.id.getAssertion", 'challenge': data['challenge'], 'origin': facet } client_data = json.dumps(client_data) client_param = H(client_data) # Unwrap: privu, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = chr(1 if touch else 0) counter = struct.pack('>I', self.counter) digest = H(app_param + touch + counter + client_param) signature = privu.sign_dsa_asn1(digest) raw_response = touch + counter + signature return json.dumps({ "clientData": websafe_encode(client_data), "signatureData": websafe_encode(raw_response), "challenge": data['challenge'], })
def getAssertion(self, request, facet="https://www.example.com", touch=False): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData(typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet) client_data = client_data.json client_param = H(client_data) # Unwrap: privu, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = chr(1 if touch else 0) counter = struct.pack('>I', self.counter) digest = H(app_param + touch + counter + client_param) signature = privu.sign_dsa_asn1(digest) raw_response = touch + counter + signature return SignResponse(clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle)
def register(self, data, facet="https://www.example.com", ): """ data = { "version": "U2F_V2", "challenge": string, //b64 encoded challenge "appId": string, //app_id } """ if isinstance(data, basestring): data = json.loads(data) if data['version'] != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % data['version']) # Client data client_data = { 'typ': "navigator.id.finishEnrollment", 'challenge': data['challenge'], 'origin': facet } client_data = json.dumps(client_data) client_param = H(client_data) # ECC key generation privu = EC.gen_params(CURVE) privu.gen_key() pub_key = str(privu.pub().get_der())[-65:] # Store key_handle = rand_bytes(64) app_param = H(data['appId']) self.keys[key_handle] = (privu, app_param) # Attestation signature cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV)) cert = CERT digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key) signature = cert_priv.sign_dsa_asn1(digest) raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \ key_handle + cert + signature return json.dumps({ "registrationData": websafe_encode(raw_response), "clientData": websafe_encode(client_data), })
def register(self, request, facet="https://www.example.com"): """ RegisterRequest = { "version": "U2F_V2", "challenge": string, //b64 encoded challenge "appId": string, //app_id } """ if not isinstance(request, RegisterRequest): request = RegisterRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) # Client data client_data = ClientData( typ='navigator.id.finishEnrollment', challenge=request['challenge'], origin=facet ) client_data = client_data.json client_param = H(client_data) # ECC key generation privu = EC.gen_params(CURVE) privu.gen_key() pub_key = str(privu.pub().get_der())[-65:] # Store key_handle = rand_bytes(64) app_param = request.appParam self.keys[key_handle] = (privu, app_param) # Attestation signature cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV)) cert = CERT digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key) signature = cert_priv.sign_dsa_asn1(digest) raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \ key_handle + cert + signature return RegisterResponse( registrationData=websafe_encode(raw_response), clientData=websafe_encode(client_data), )
def register(self, request, facet="https://www.example.com"): """ RegisterRequest = { "version": "U2F_V2", "challenge": string, //b64 encoded challenge "appId": string, //app_id } """ if not isinstance(request, RegisterRequest): request = RegisterRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) # Client data client_data = ClientData(typ='navigator.id.finishEnrollment', challenge=request['challenge'], origin=facet) client_data = client_data.json client_param = H(client_data) # ECC key generation privu = EC.gen_params(CURVE) privu.gen_key() pub_key = str(privu.pub().get_der())[-65:] # Store key_handle = rand_bytes(64) app_param = request.appParam self.keys[key_handle] = (privu, app_param) # Attestation signature cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV)) cert = CERT digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key) signature = cert_priv.sign_dsa_asn1(digest) raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \ key_handle + cert + signature return RegisterResponse( registrationData=websafe_encode(raw_response), clientData=websafe_encode(client_data), )
def create(cls, app_id, devices, challenge=None): if challenge is None: challenge = os.urandom(32) return cls( appId=app_id, registeredKeys=devices, challenge=websafe_encode(challenge) )
def start_register(app_id, challenge=None): if challenge is None: challenge = rand_bytes(32) return RegisterRequest( version=VERSION, appId=app_id, challenge=websafe_encode(challenge) )
def complete_register(request, response, valid_facets=None): request = RegisterRequest.wrap(request) response = RegisterResponse.wrap(response) _validate_client_data(response.clientData, request.challenge, "navigator.id.finishEnrollment", valid_facets) raw_response = RawRegistrationResponse(request.appParam, response.clientParam, response.registrationData) raw_response.verify_csr_signature() return DeviceRegistration( appId=request.appId, keyHandle=websafe_encode(raw_response.key_handle), publicKey=websafe_encode( raw_response.pub_key)), raw_response.certificate
def getAssertion(self, facet, app_id, challenge, key, touch_byte=1): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ key = RegisteredKey.wrap(key) if key.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % key.version) if key.keyHandle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData(typ=Type.SIGN.value, challenge=challenge, origin=facet) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # Unwrap: priv_key, app_param = self.keys[key.keyHandle] # Increment counter self.counter += 1 # Create signature touch = six.int2byte(touch_byte) counter = struct.pack('>I', self.counter) data = app_param + touch + counter + client_param signer = priv_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = touch + counter + signature return SignResponse(clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=key['keyHandle'])
def test_websafe_encode(self): self.assertEqual(websafe_encode(b''), u'') self.assertEqual(websafe_encode(b'f'), u'Zg') self.assertEqual(websafe_encode(b'fo'), u'Zm8') self.assertEqual(websafe_encode(b'foo'), u'Zm9v') self.assertEqual(websafe_encode(b'foob'), u'Zm9vYg') self.assertEqual(websafe_encode(b'fooba'), u'Zm9vYmE') self.assertEqual(websafe_encode(b'foobar'), u'Zm9vYmFy')
def start_authenticate(device, challenge=None): device = DeviceRegistration.wrap(device) if challenge is None: challenge = rand_bytes(32) return SignRequest(version=VERSION, appId=device.appId, keyHandle=device.keyHandle, challenge=websafe_encode(challenge))
def create(cls, app_id, registered_keys, challenge=None): if challenge is None: challenge = os.urandom(32) return cls(appId=app_id, registerRequests=[ RegisterRequest(version=U2F_V2, challenge=websafe_encode(challenge)) ], registeredKeys=registered_keys)
def complete_register(request, response, valid_facets=None): request = RegisterRequest.wrap(request) response = RegisterResponse.wrap(response) _validate_client_data(response.clientData, request.challenge, "navigator.id.finishEnrollment", valid_facets) raw_response = RawRegistrationResponse( request.appParam, response.clientParam, response.registrationData ) raw_response.verify_csr_signature() return DeviceRegistration( appId=request.appId, keyHandle=websafe_encode(raw_response.key_handle), publicKey=websafe_encode(raw_response.pub_key) ), raw_response.certificate
def start_authenticate(device, challenge=None): device = DeviceRegistration.wrap(device) if challenge is None: challenge = rand_bytes(32) return SignRequest( version=VERSION, appId=device.appId, keyHandle=device.keyHandle, challenge=websafe_encode(challenge) )
def create(cls, app_id, devices, challenge=None): # When the challenge is set we encode and hash it to be used in the signature if challenge is not None: encoded_challenge = challenge.encode('ascii') challenge = sha_256(encoded_challenge) if challenge is None: challenge = os.urandom(32) return cls(appId=app_id, registeredKeys=devices, challenge=websafe_encode(challenge))
def create(cls, app_id, registered_keys, challenge=None): if challenge is None: challenge = os.urandom(32) return cls( appId=app_id, registerRequests=[RegisterRequest( version=U2F_V2, challenge=websafe_encode(challenge) )], registeredKeys=registered_keys )
def test_invalid_signature(self): device = SoftU2FDevice() request = begin_registration(APP_ID) data = request.data_for_client response = device.register(FACET, data['appId'], data['registerRequests'][0]) response = RegisterResponse.wrap(response) raw_data = response.registrationData.bytes raw_data = raw_data[:-4] + b'\0\0\0\0' response['registrationData'] = websafe_encode(raw_data) response = response.json self.assertRaisesRegex(ValueError, 'signature', complete_registration, request.json, response)
def webauthnuser(self): d = json.loads(self.json_data) # We manually need to convert the pubkey from DER format (used in our # former U2F implementation) to the format required by webauthn. This # is based on the following example: # https://www.w3.org/TR/webauthn/#sctn-encoded-credPubKey-examples pub_key = pub_key_from_der( websafe_decode(d['publicKey'].replace('+', '-').replace('/', '_'))) pub_key = binascii.unhexlify( 'A5010203262001215820{:064x}225820{:064x}'.format( pub_key.public_numbers().x, pub_key.public_numbers().y)) return webauthn.WebAuthnUser(d['keyHandle'], self.user.email, str(self.user), settings.SITE_URL, d['keyHandle'], websafe_encode(pub_key), 1, urlparse(settings.SITE_URL).netloc)
def serialize(self): return websafe_encode(self.app_param + self.chal_param + self.data)
def publicKey(self): return websafe_encode(self.pub_key)
def keyHandle(self): return websafe_encode(self.key_handle)
def serialize(self): return json.dumps({ 'challenge': websafe_encode(self.challenge) })
def test_websafe_encode_unicode(self): self.assertEqual(websafe_encode(u''), u'') self.assertEqual(websafe_encode(u'foobar'), u'Zm9vYmFy')
def serialize(self): return json.dumps({ 'appId': self.app_id, 'facets': self.facets, 'challenge': websafe_encode(self.challenge) })