o
    z                     @   sp   d Z ddlZddlZddlZddlmZ ddlmZ ddlmZ ddlmZ e	 fddZ
G d	d
 d
eZdS )aN  Implement a high level U2F API analogous to the javascript API spec.

This modules implements a high level U2F API that is analogous in spirit
to the high level U2F javascript API.  It supports both registration and
authetication.  For the purposes of this API, the "origin" is the hostname
of the machine this library is running on.
    N)errors)hardware)hidtransport)modelc              	   C   sH   t  }|D ]}zttj|d| dW   S  tjy   Y qw t )zEObtains a U2FInterface for the first valid local U2FHID device found.)	transport)security_keyorigin)r   DiscoverLocalHIDU2FDevicesU2FInterfacer   SecurityKeyr   UnsupportedVersionExceptionNoDeviceFoundError)r   hid_transportst r   2/tmp/google-cloud-sdk/lib/third_party/pyu2f/u2f.pyGetLocalU2FInterface!   s   r   c                   @   s8   e Zd ZdZe fddZdd Zdd Zdd	 Z	d
S )r
   a  High level U2F interface.

  Implements a high level interface in the spirit of the FIDO U2F
  javascript API high level interface.  It supports registration
  and authentication (signing).

  IMPORTANT NOTE: This class does NOT validate the app id against the
  origin.  In particular, any user can assert any app id all the way to
  the device.  The security model of a python library is such that doing
  so would not provide significant benfit as it could be bypassed by the
  caller talking to a lower level of the API.  In fact, so could the origin
  itself.  The origin is still set to a plausible value (the hostname) by
  this library.

  TODO(user): Figure out a plan on how to address this gap/document the
  consequences of this more clearly.
  c                 C   s&   || _ || _| j dkrt d S )Ns   U2F_V2)r   r   
CmdVersionr   r   )selfr   r   r   r   r   __init__C   s
   zU2FInterface.__init__c                 C   sj  t t jj|| j}| | }| |}|D ]M}z|jdkr"W q| j|||j	d}t
d t
jy?   t
t
jj t
jyQ }	 zW Y d}	~	qd}	~	w t
jye }	 zt
t
jj|	d}	~	ww tdD ]C}
z| j||}t ||W   S  t
jy }	 z| j  td W Y d}	~	qjd}	~	w t
jy }	 zt
t
jj|	d}	~	ww t
t
jj)a  Registers app_id with the security key.

    Executes the U2F registration flow with the security key.

    Args:
      app_id: The app_id to register the security key against.
      challenge: Server challenge passed to the security key.
      registered_keys: List of keys already registered for this app_id+user.

    Returns:
      RegisterResponse with key_handle and attestation information in it (
        encoded in FIDO U2F binary format within registration_data field).

    Raises:
      U2FError: There was some kind of problem with registration (e.g.
        the device was already registered or there was a timeout waiting
        for the test of user presence).
    U2F_V2TzShould Never HappenN         ?)r   
ClientDataTYP_REGISTRATIONr   InternalSHA256GetJsonversionr   CmdAuthenticate
key_handler   HardwareErrorTUPRequiredErrorU2FErrorDEVICE_INELIGIBLEInvalidKeyHandleErrorBAD_REQUESTrangeCmdRegisterRegisterResponseCmdWinktimesleepTIMEOUT)r   app_id	challengeregistered_keysclient_datachallenge_param	app_paramkeyrespe_r   r   r   RegisterJ   sF   




zU2FInterface.Registerc                 C   s  t t jj|| j}| |}| | }d}|D ]_}z;|jdkr$W qtdD ]-}	z| j	|||j
}
t |j
|
|W   W   S  tjyU   | j  td Y q(w W q tjye   |d7 }Y q tjyy } zttjj|d}~ww |t|krttjjttjj)a  Authenticates app_id with the security key.

    Executes the U2F authentication/signature flow with the security key.

    Args:
      app_id: The app_id to register the security key against.
      challenge: Server challenge passed to the security key as a bytes object.
      registered_keys: List of keys already registered for this app_id+user.

    Returns:
      SignResponse with client_data, key_handle, and signature_data.  The client
      data is an object, while the signature_data is encoded in FIDO U2F binary
      format.

    Raises:
      U2FError: There was some kind of problem with authentication (e.g.
        there was a timeout while waiting for the test of user presence.)
    r   r   r   r      N)r   r   TYP_AUTHENTICATIONr   r   r   r   r&   r   r   r   SignResponser   r!   r)   r*   r+   r$   r    r"   r%   lenr#   r,   )r   r-   r.   r/   r0   r2   r1   num_invalid_keysr3   r6   r4   r5   r   r   r   Authenticate   s>   




zU2FInterface.Authenticatec                 C   s   t  }||  | S )N)hashlibsha256updateencodedigest)r   stringmdr   r   r   r      s   zU2FInterface.InternalSHA256N)
__name__
__module____qualname____doc__socketgethostnamer   r7   r=   r   r   r   r   r   r
   0   s    91r
   )rH   r>   rI   r*   pyu2fr   r   r   r   rJ   r   objectr
   r   r   r   r   <module>   s   