o
    l>j=                     @  s<  d dl mZ d dlZd dlZd dlmZmZmZmZ d dl	m
Z d dlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z) e*e+Z,eee-gdf Z.ee/ge0f Z1d(ddZ2d)ddZ3	d*d+ddZ4d,ddZ5d-d$d%Z6G d&d' d'Z7dS ).    )annotationsN)AnyCallableMappingSequence)InvalidSignature)constant_time   )CoseKeyverify_rp_id)websafe_decodewebsafe_encode)AttestationConveyancePreferenceAttestationObjectAttestedCredentialDataAuthenticationResponseAuthenticatorAttachmentAuthenticatorDataAuthenticatorSelectionCriteriaCollectedClientDataCredentialCreationOptionsCredentialRequestOptions"PublicKeyCredentialCreationOptionsPublicKeyCredentialDescriptorPublicKeyCredentialParameters!PublicKeyCredentialRequestOptionsPublicKeyCredentialRpEntityPublicKeyCredentialTypePublicKeyCredentialUserEntityRegistrationResponseResidentKeyRequirementUserVerificationRequirementrp_idstrreturnVerifyOriginc                   s    fddS )Nc                   s
   t  | S Nr   )or#    A/home/thesage/.local/lib/python3.10/site-packages/fido2/server.py<lambda>G   s   
 z'_verify_origin_for_rp.<locals>.<lambda>r*   r)   r*   r)   r+   _verify_origin_for_rpF   s   r-   	challengebytes | Nonebytesc                 C  s@   | d u rt d} | S t| tstdt| dk rtd| S )N    z)Custom challenge must be of type 'bytes'.   z&Custom challenge length must be >= 16.)osurandom
isinstancer0   	TypeErrorlen
ValueError)r.   r*   r*   r+   _validata_challengeJ   s   

r9   
credentialr   r   c                 C  s   t tj| j|dS )a  Converts an AttestedCredentialData to a PublicKeyCredentialDescriptor.

    :param credential: AttestedCredentialData containing the credential ID to use.
    :param transports: Optional list of AuthenticatorTransport strings to add to the
        descriptor.
    :return: A descriptor of the credential, for use with register_begin or
        authenticate_begin.
    :rtype: PublicKeyCredentialDescriptor
    )typeid
transports)r   r   
PUBLIC_KEYcredential_id)r:   r=   r*   r*   r+   to_descriptorU   s
   r@   credsGSequence[AttestedCredentialData | PublicKeyCredentialDescriptor] | None.Sequence[PublicKeyCredentialDescriptor] | Nonec                 C  s   | d u rd S dd | D S )Nc                 S  s(   g | ]}t |trt|nt|qS r*   )r5   r   r@   r   	from_dict).0cr*   r*   r+   
<listcomp>m   s    
z%_wrap_credentials.<locals>.<listcomp>r*   )rA   r*   r*   r+   _wrap_credentialsh   s
   rH   attestation_objectr   client_data_hashNonec                 C  s   dS )zIgnore attestation.Nr*   )rI   rJ   r*   r*   r+   _ignore_attestationw   s    rL   c                   @  sp   e Zd ZdZ			d-d.ddZ						d/d0ddZd1d d!Z				d2d3d#d$Zd4d(d)Ze	d5d+d,Z
dS )6Fido2Servera@  FIDO2 server.

    :param rp: Relying party data as `PublicKeyCredentialRpEntity` instance.
    :param attestation: (optional) Requirement on authenticator attestation.
    :param verify_origin: (optional) Alternative function to validate an origin.
    :param verify_attestation: (optional) function to validate attestation, which is
        invoked with attestation_object and client_data_hash. It should return nothing
        and raise an exception on failure. By default, attestation is ignored.
        Attestation is also ignored if `attestation` is set to `none`.
    Nrpr   attestation&AttestationConveyancePreference | Noneverify_originVerifyOrigin | Noneverify_attestationVerifyAttestation | Nonec                 C  sr   t || _| jjd usJ |pt| jj| _d | _t|| _dd t	
 D | _|p,t| _td| j  d S )Nc                 S  s   g | ]	}t tj|d qS ))r;   alg)r   r   r>   )rE   rU   r*   r*   r+   rG      s    z(Fido2Server.__init__.<locals>.<listcomp>z Fido2Server initialized for RP: )r   rD   rN   r<   r-   _verifytimeoutr   rO   r
   supported_algorithmsallowed_algorithmsrL   _verify_attestationloggerdebug)selfrN   rO   rQ   rS   r*   r*   r+   __init__   s   

zFido2Server.__init__userr   credentialsrB   resident_key_requirementResidentKeyRequirement | Noneuser_verification"UserVerificationRequirement | Noneauthenticator_attachmentAuthenticatorAttachment | Noner.   r/   r%   %tuple[CredentialCreationOptions, Any]c           
      C  s   | j stdt|}t|}| ||}	tdddd |p g D   tt	| j
t||| j | j|t|||frBt|||dnd| j|d	d	|	fS )
av  Return a PublicKeyCredentialCreationOptions registration object and
        the internal state dictionary that needs to be passed as is to the
        corresponding `register_complete` call.

        :param user: The dict containing the user data.
        :param credentials: The list of previously registered credentials, these can be
            of type AttestedCredentialData, or PublicKeyCredentialDescriptor.
        :param resident_key_requirement: The desired RESIDENT_KEY_REQUIREMENT level.
        :param user_verification: The desired USER_VERIFICATION level.
        :param authenticator_attachment: The desired AUTHENTICATOR_ATTACHMENT
            or None to not provide a preference (and get both types).
        :param challenge: A custom challenge to sign and verify or None to use
            OS-specific random bytes.
        :return: Registration data, internal state.z!Server has no allowed algorithms.z1Starting new registration, existing credentials: , c                 s      | ]}|j  V  qd S r'   r<   hexrE   dr*   r*   r+   	<genexpr>       z-Fido2Server.register_begin.<locals>.<genexpr>)re   resident_keyrc   N)	rN   r_   r.   pub_key_cred_paramsrW   exclude_credentialsauthenticator_selectionrO   
extensions
public_key)rY   r8   r9   rH   _make_internal_stater[   r\   joinr   r   rN   r   rD   rW   anyr   rO   )
r]   r_   r`   ra   rc   re   r.   rt   descriptorsstater*   r*   r+   register_begin   sH   zFido2Server.register_beginresponse(RegistrationResponse | Mapping[str, Any]r   c                 C  s  t |}|jj}|jj}|jtjjkrt	d| 
|js"t	dtt|d |js1t	dt| jjp8d|jjsAt	d|j sJt	d|d tjkrZ|j sZt	d	| jd
tjfvrrtd|j  | ||j |j}|j d
us|J t!d|j j"#   |S )a(  Verify the correctness of the registration data received from
        the client.

        :param state: The state data returned by the corresponding
            `register_begin`.
        :param response: The registration response from the client.
        :return: The authenticator data
        &Incorrect type in CollectedClientData.&Invalid origin in CollectedClientData.r.   Wrong challenge in response.    Wrong RP ID hash in response.User Present flag not set.rc   z;User verification required, but User Verified flag not set.NzVerifying attestation of type zNew credential registered: )$r    rD   r}   client_datarI   r;   r   TYPECREATEr8   rV   originr   bytes_eqr   r.   rN   id_hash	auth_data
rp_id_hashis_user_presentr"   REQUIREDis_user_verifiedrO   r   NONEr[   r\   fmtrZ   hashcredential_datainfor?   rk   )r]   r{   r}   registrationr   rI   r   r*   r*   r+   register_complete   sD   


zFido2Server.register_complete$tuple[CredentialRequestOptions, Any]c              	   C  sr   t |}t|}| ||}|du rtd ntdddd |D   tt|| j| j	j
|||dd|fS )	aR  Return a PublicKeyCredentialRequestOptions assertion object and the internal
        state dictionary that needs to be passed as is to the corresponding
        `authenticate_complete` call.

        :param credentials: The list of previously registered credentials, these can be
            of type AttestedCredentialData, or PublicKeyCredentialDescriptor.
        :param user_verification: The desired USER_VERIFICATION level.
        :param challenge: A custom challenge to sign and verify or None to use
            OS-specific random bytes.
        :return: Assertion data, internal state.Nz/Starting new authentication without credentialsz.Starting new authentication, for credentials: rh   c                 s  ri   r'   rj   rl   r*   r*   r+   rn   3  ro   z1Fido2Server.authenticate_begin.<locals>.<genexpr>)r.   rW   r#   allow_credentialsrc   rt   ru   )r9   rH   rw   r[   r\   rx   r   r   rW   rN   r<   )r]   r`   rc   r.   rt   rz   r{   r*   r*   r+   authenticate_begin  s,   
zFido2Server.authenticate_begin Sequence[AttestedCredentialData]*AuthenticationResponse | Mapping[str, Any]r   c           
   	   C  s$  t |}|j}|jj}|jj}|jj}|jtj	j
krtd| |js)tdtt|d |js8tdt| jjp?d|jsGtd| sOtd|d tjkr^| s^td	|D ]-}	|	j|krz|	j||j | W n ty~   td
w td|    |	  S q`td)a  Verify the correctness of the assertion data received from
        the client.

        :param state: The state data returned by the corresponding
            `register_begin`.
        :param credentials: The list of previously registered credentials.
        :param credential_id: The credential id from the client response.
        :param client_data: The client data.
        :param auth_data: The authenticator data.
        :param signature: The signature provided by the client.r   r   r.   r   r   r   r   rc   z;User verification required, but user verified flag not set.zInvalid signature.zCredential authenticated: zUnknown credential ID.)!r   rD   raw_idr}   r   authenticator_data	signaturer;   r   r   GETr8   rV   r   r   r   r   r.   rN   r   r   r   r"   r   r   r?   rv   verifyr   _InvalidSignaturer[   r   rk   )
r]   r{   r`   r}   authenticationr?   r   r   r   credr*   r*   r+   authenticate_completeD  sD   

z!Fido2Server.authenticate_completer0   c                 C  s   t | |dS )Nr.   rc   )r   r   r*   r*   r+   rw   z  s   z Fido2Server._make_internal_state)NNN)rN   r   rO   rP   rQ   rR   rS   rT   )NNNNNN)r_   r   r`   rB   ra   rb   rc   rd   re   rf   r.   r/   r%   rg   )r}   r~   r%   r   )NNNN)r`   rB   rc   rd   r.   r/   r%   r   )r`   r   r}   r   r%   r   )r.   r0   rc   rd   )__name__
__module____qualname____doc__r^   r|   r   r   r   staticmethodrw   r*   r*   r*   r+   rM   }   s,    
D:
,6rM   )r#   r$   r%   r&   )r.   r/   r%   r0   r'   )r:   r   r%   r   )rA   rB   r%   rC   )rI   r   rJ   r0   r%   rK   )8
__future__r   loggingr3   typingr   r   r   r   cryptography.exceptionsr   r   cryptography.hazmat.primitivesr   coser
   rpidr   utilsr   r   webauthnr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   	getLoggerr   r[   r0   VerifyAttestationr$   boolr&   r-   r9   r@   rH   rL   rM   r*   r*   r*   r+   <module>   s(   X




