o
    l>j                     @  s   d dl mZ d dl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 dd Zdd Zdd Zdd Zdd ZG dd dZdS )    )annotationsN)AnyMappingSequencecast)
InvalidTag)AESGCM   )cbor)sha256   )Ctap2Info)PinProtocol_PinUvc                 C  "   t jt j d}|| |  S N)wbits)zlibcompressobj	MAX_WBITScompressflushdatao r   E/home/thesage/.local/lib/python3.10/site-packages/fido2/ctap2/blob.py	_compress,      r   c                 C  r   r   )r   decompressobjr   
decompressr   r   r   r   r   _decompress1   r   r"   c                 C  s   dt d|  S )Ns   blobz<Q)structpack)	orig_sizer   r   r   _lb_ad6   s   r&   c                 C  s<   t |}td}t| }||t|t|}|||dS )N   )r   r	      )lenosurandomr   encryptr   r&   )keyr   r%   nonceaesgcm
ciphertextr   r   r   _lb_pack:   s   
r1   c              
   C  sn   z|d }|d }|d }t | }|||t|}||fW S  tttfy,   td ty6   tdw )Nr   r	   r(   zInvalid entryz	Wrong key)r   decryptr&   	TypeError
IndexErrorKeyError
ValueErrorr   )r-   entryr0   r.   r%   r/   
compressedr   r   r   
_lb_unpackH   s   
r9   c                   @  s`   e Zd ZdZed!ddZ		d"d#ddZd$ddZd%ddZd&ddZ	d'ddZ
d(dd ZdS ))
LargeBlobsaJ  Implementation of the CTAP2.1 Large Blobs API.

    Getting a largeBlobKey for a credential is done via the LargeBlobKey extension.

    :param ctap: An instance of a CTAP2 object.
    :param pin_uv_protocol: An instance of a PinUvAuthProtocol.
    :param pin_uv_token: A valid PIN/UV Auth Token for the current CTAP session.
    infor   returnboolc                 C  s   | j ddu S )N
largeBlobsT)optionsget)r;   r   r   r   is_supported`   s   zLargeBlobs.is_supportedNctapr   pin_uv_protocolPinProtocol | Nonepin_uv_tokenbytes | Nonec                 C  sL   |  |js
td|| _| jjjd | _|r!|r!t||| _d S d | _d S )Nz)Authenticator does not support LargeBlobs@   )rA   r;   r6   rB   max_msg_sizemax_fragment_lengthr   pin_uv)selfrB   rC   rE   r   r   r   __init__d   s   
zLargeBlobs.__init__Sequence[Mapping[int, Any]]c                 C  s   d}d}	 | j j|| jdd }||7 }t|| jk rn|| j7 }q|dd |dd }}|t|dd kr;g S ttttt	f  t
|S )zsGets the entire contents of the Large Blobs array.

        :return: The CBOR decoded list of Large Blobs.
        r       T)r@   r   Ni)rB   large_blobsrI   r)   r   r   r   r   intr   r
   decode)rK   offsetbuffragmentr   checkr   r   r   read_blob_arrayu   s   
zLargeBlobs.read_blob_array
blob_arrayNonec           
      C  s   t |ts	tdt|}|t|dd 7 }d}t|}||k rpt|| | j}||||  }| j	rQdt
d| t| }| j	jj}| j	j| j	j|}	nd}	d}| jj|||dkr`|nd||	d ||7 }||k s"dS dS )zoWrites the entire Large Blobs array.

        :param blob_array: A list to write to the Authenticator.
        zlarge-blob array must be a listN   r   s"    z<I)setlengthrC   pin_uv_param)
isinstancelistr3   r
   encoder   r)   minrI   rJ   r#   r$   protocolVERSIONauthenticatetokenrB   rO   )
rK   rW   r   rR   sizeln_setmsgrC   r\   r   r   r   write_blob_array   s:   



zLargeBlobs.write_blob_arraylarge_blob_keybytesc              
   C  sZ   |   D ]&}zt||\}}t|}t||kr|W   S W q ttjfy*   Y qw dS )zGets the Large Blob stored for a single credential.

        :param large_blob_key: The largeBlobKey for the credential, or None.
        :returns: The decrypted and deflated value stored for the credential.
        N)rV   r9   r"   r)   r6   r   error)rK   rj   r7   r8   r%   decompressedr   r   r   get_blob   s   
zLargeBlobs.get_blobr   c              	   C  sv   |du}g }|   D ]}z	t|| d}W q
 ty#   || Y q
w |dur0|t|| |r9| | dS dS )a   Stores a Large Blob for a single credential.

        Any existing entries for the same credential will be replaced.

        :param large_blob_key: The largeBlobKey for the credential.
        :param data: The data to compress, encrypt and store.
        NT)rV   r9   r6   appendr1   ri   )rK   rj   r   modifiedentriesr7   r   r   r   put_blob   s   
zLargeBlobs.put_blobc                 C  s   |  |d dS )zDeletes any Large Blob(s) stored for a single credential.

        :param large_blob_key: The largeBlobKey for the credential.
        N)rr   )rK   rj   r   r   r   delete_blob   s   zLargeBlobs.delete_blob)r;   r   r<   r=   )NN)rB   r   rC   rD   rE   rF   )r<   rM   )rW   rM   r<   rX   )rj   rk   r<   rF   )rj   rk   r   rF   r<   rX   )rj   rk   r<   rX   )__name__
__module____qualname____doc__staticmethodrA   rL   rV   ri   rn   rr   rs   r   r   r   r   r:   V   s    	


(
r:   )
__future__r   r*   r#   r   typingr   r   r   r   cryptography.exceptionsr   +cryptography.hazmat.primitives.ciphers.aeadr    r
   utilsr   baser   r   pinr   r   r   r"   r&   r1   r9   r:   r   r   r   r   <module>   s"   