
    S!                         S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJ	r	  SSKJ
r
  SSKJr  SrSrSrSrS	r " S
 S\R$                  5      rg)z4Class to offload the end to end flow of U2F signing.    N)errors)model)baseauthenticatorSK_SIGNING_PLUGIN   ii  ij  c                   v    \ rS rSrSrS r\R                  R                  4S jr	S r
S rS rS rS	 rS
 rSrg)CustomAuthenticator%   a  Offloads U2F signing to a pluggable command-line tool.

Offloads U2F signing to a signing plugin which takes the form of a
command-line tool. The command-line tool is configurable via the
SK_SIGNING_PLUGIN environment variable.

The signing plugin should implement the following interface:

Communication occurs over stdin/stdout, and messages are both sent and
received in the form:

[4 bytes - payload size (little-endian)][variable bytes - json payload]

Signing Request JSON
{
  "type": "sign_helper_request",
  "signData": [{
      "keyHandle": <url-safe base64-encoded key handle>,
      "appIdHash": <url-safe base64-encoded SHA-256 hash of application ID>,
      "challengeHash": <url-safe base64-encoded SHA-256 hash of ClientData>,
      "version": U2F protocol version (usually "U2F_V2")
      },...],
  "timeoutSeconds": <security key touch timeout>
}

Signing Response JSON
{
  "type": "sign_helper_reply",
  "code": <result code>.
  "errorDetail": <text description of error>,
  "responseData": {
    "appIdHash": <url-safe base64-encoded SHA-256 hash of application ID>,
    "challengeHash": <url-safe base64-encoded SHA-256 hash of ClientData>,
    "keyHandle": <url-safe base64-encoded key handle>,
    "version": <U2F protocol version>,
    "signatureData": <url-safe base64-encoded signature>
  }
}

Possible response error codes are:

  NoError            = 0
  UnknownError       = -127
  TouchRequired      = 0x6985
  WrongData          = 0x6a80
c                     Xl         g )Norigin)selfr   s     8lib/third_party/pyu2f/convenience/customauthenticator.py__init__CustomAuthenticator.__init__U   s    K    c                 r   [         R                  R                  [        5      nUc)  [        R
                  " SR                  [        5      5      eU R                  XU R                  5      u  pVU" S5        U R                  U/U5      nUS   US   4nXX   n	U	R                  5       n
U R                  XU5      $ )See base class.z{} env var is not setz*Please insert and touch your security key
	keyHandlechallengeHash)osenvirongetSK_SIGNING_PLUGIN_ENV_VARr   PluginErrorformat_BuildPluginRequestr   _CallPluginencode_BuildAuthenticatorResponse)r   app_idchallenge_dataprint_callback
plugin_cmdclient_data_mapsigning_inputresponsekey_challenge_pairclient_data_jsonclient_datas              r   Authenticate CustomAuthenticator.AuthenticateX   s    
  9:J6 &'@ AC C &*%=%=&-"O @Am<H #;//1JK&:"))+K++FJJr   c                 L    [         R                  R                  [        5      SL$ )r   N)r   r   r   r   )r   s    r   IsAvailableCustomAuthenticator.IsAvailablep   s    ::>>34D@@r   c                    0 n/ nU R                  U R                  U5      5      nU H  nUS   nU R                  UR                  5      n	US   n
[        R                  " [        R                  R
                  U
U5      R                  5       nU R                  U R                  U5      5      nUR                  UUU	UR                  S.5        X4nXU'   M     SU[        SS.nU[        R                  " U5      4$ )z:Builds a JSON request in the form that the plugin expects.key	challenge)	appIdHashr   r   versionsign_helper_requestT)typesignDatatimeoutSecondslocalAlways)_Base64Encode_SHA256
key_handler   
ClientDataTYP_AUTHENTICATIONGetJsonappendr4   U2F_SIGNATURE_TIMEOUT_SECONDSjsondumps)r   r!   r"   r   r%   encoded_challengesapp_id_hash_encodedchallenge_itemr1   key_handle_encodedraw_challenger)   challenge_hash_encodedr(   signing_requests                  r   r   'CustomAuthenticator._BuildPluginRequestt   s   O,,T\\&-AB(5!c--cnn=$[1m))



-
-

 ') 
  $11
,,'
( * *1)[[	! 	 /G,<()1 )6 &&7	O DJJ777r   c                 n    U R                  U5      n[        US   5      n[        US   5      nUUUUS.nU$ )z,Builds the response to return to the caller.signatureDatar   )
clientDatarM   applicationIdr   )r:   str)r   r!   r*   plugin_responseencoded_client_datasignature_datar<   r'   s           r   r    /CustomAuthenticator._BuildAuthenticatorResponse   sM    ,,[99:N_[12J *'	H Or   c                    [        U5      n[        R                  " SU5      nXBR                  5       -   n[        R
                  " U[        R                  [        R                  S9nUR                  U5      S   nUR                  5       nUSS n	[        R                  " SU	5      S   n
USS nU
[        U5      :w  a0  [        R                  " SR                  U
[        U5      U5      5      e [        R                  " UR                  5       5      nUR#                  S5      S	:w  aG  S
R                  U5      nUR#                  S5      nU(       a  USU-   -  n[        R                  " U5      eUR#                  S5      nUc%  [        R                  " SR                  U5      5      eU[$        :X  a.  [        R&                  " [        R&                  R(                  5      eU[*        :X  a.  [        R&                  " [        R&                  R,                  5      eU[.        :w  a6  [        R                  " SR                  UUR#                  S5      U5      5      eUR#                  S5      nUc%  [        R0                  " SR                  U5      5      eU$ ! [          a&    [        R                  " SR                  U5      5      ef = f)z,Calls the plugin and validates the response.z<I)stdinstdoutr   N   zAPlugin response length {} does not match data {} (exit_status={})z/Plugin returned invalid output (exit_status={})r6   sign_helper_replyz6Plugin returned invalid response type (exit_status={})errorDetailz. Additional information:
codez+Plugin missing result code (exit_status={})z1Plugin failed with error {} - {} (exit_status={})responseDatazAPlugin returned output with missing responseData (exit_status={}))lenstructpackr   
subprocessPopenPIPEcommunicatewaitunpackr   r   r   rB   loadsdecode
ValueErrorr    SK_SIGNING_PLUGIN_TOUCH_REQUIREDU2FErrorTIMEOUTSK_SIGNING_PLUGIN_WRONG_DATADEVICE_INELIGIBLESK_SIGNING_PLUGIN_NO_ERRORPluginErrors)r   cmd
input_jsoninput_lengthlength_bytes_lerequestsign_processrW   exit_statusresponse_len_leresponse_lenr'   json_responseerror_stringerror_detailresult_coderesponse_datas                    r   r   CustomAuthenticator._CallPlugin   sw    z?Lkk$5O 1 1 33G ##C*4//+5??<L %%g.q1F##%K RajO==7:LabzHs8}$
M6,H{;= =
5jj!23m  $77MTTU`al"&&}5l
5DD|,,  ##F+KL &{ 35 5 66OOFOO3344	4	4OOFOO==>>	2	2
=6+##M2    "%%n5M
M6+    K  5P &{ 35 55s   /$J 0Kc                     [         R                  " 5       nUR                  UR                  5       5        UR	                  5       $ )z Helper method to perform SHA256.)hashlibsha256updater   digest)r   stringmds      r   r;   CustomAuthenticator._SHA256   s,    		BIIfmmo99;r   c                 h    [         R                  " U5      R                  5       R                  S5      $ )zEHelper method to base64 encode, strip padding, and return str
result.=)base64urlsafe_b64encoderg   rstrip)r   
bytes_datas     r   r:   !CustomAuthenticator._Base64Encode   s)     %%j188:AA#FFr   r   N)__name__
__module____qualname____firstlineno____doc__r   sysstderrwriter+   r.   r   r    r   r;   r:   __static_attributes__ r   r   r	   r	   %   sE    -^ #&**"2"2K0A&8P@DGr   r	   )r   r   r   rB   r   r^   r`   r   pyu2fr   r   pyu2f.conveniencer   r   rA   rn   ri   rl   BaseAuthenticatorr	   r   r   r   <module>r      s]    ;    	   
   //  !  #)  % PG+== PGr   