81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
# Copyright 2016 Google Inc. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Implements data model for the library.
|
|
|
|
This module implements basic data model objects that are necessary
|
|
for interacting with the Security Key as well as for implementing
|
|
the higher level components of the U2F protocol.
|
|
"""
|
|
|
|
import base64
|
|
import json
|
|
|
|
from pyu2f import errors
|
|
|
|
|
|
class ClientData(object):
|
|
"""FIDO U2F ClientData.
|
|
|
|
Implements the ClientData object of the FIDO U2F protocol.
|
|
"""
|
|
TYP_AUTHENTICATION = 'navigator.id.getAssertion'
|
|
TYP_REGISTRATION = 'navigator.id.finishEnrollment'
|
|
|
|
def __init__(self, typ, raw_server_challenge, origin):
|
|
if typ not in [ClientData.TYP_REGISTRATION, ClientData.TYP_AUTHENTICATION]:
|
|
raise errors.InvalidModelError()
|
|
self.typ = typ
|
|
self.raw_server_challenge = raw_server_challenge
|
|
self.origin = origin
|
|
|
|
def GetJson(self):
|
|
"""Returns JSON version of ClientData compatible with FIDO spec."""
|
|
|
|
# The U2F Raw Messages specification specifies that the challenge is encoded
|
|
# with URL safe Base64 without padding encoding specified in RFC 4648.
|
|
# Python does not natively support a paddingless encoding, so we simply
|
|
# remove the padding from the end of the string.
|
|
server_challenge_b64 = base64.urlsafe_b64encode(
|
|
self.raw_server_challenge).decode()
|
|
server_challenge_b64 = server_challenge_b64.rstrip('=')
|
|
return json.dumps({'typ': self.typ,
|
|
'challenge': server_challenge_b64,
|
|
'origin': self.origin}, sort_keys=True)
|
|
|
|
def __repr__(self):
|
|
return self.GetJson()
|
|
|
|
|
|
class RegisteredKey(object):
|
|
|
|
def __init__(self, key_handle, version=u'U2F_V2'):
|
|
self.key_handle = key_handle
|
|
self.version = version
|
|
|
|
|
|
class RegisterResponse(object):
|
|
|
|
def __init__(self, registration_data, client_data):
|
|
self.registration_data = registration_data
|
|
self.client_data = client_data
|
|
|
|
|
|
class SignResponse(object):
|
|
|
|
def __init__(self, key_handle, signature_data, client_data):
|
|
self.key_handle = key_handle
|
|
self.signature_data = signature_data
|
|
self.client_data = client_data
|