
    WwgB                        d 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m	Z	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 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l m!Z! g dZ"dZ# G d dejH                        Z% G d dejH                        Z& ed       G d d             Z' G d dejP                        Z) G d de)      Z* ed       G d  d!             Z+ G d" d#e*      Z, G d$ d%e*      Z-y)&z}
This module contains the low-level building blocks for dealing with bookkeeping
around ``/ByteRange`` digests in PDF files.
    N)	dataclass)datetime)BytesIO)IOOptionalUnion)cms)hashes)genericmisc)pdf_datepdf_name
pdf_string)IncrementalPdfFileWriter)BasePdfFileWriter)SigningErrorget_pyca_cryptography_hash   )SigAuthTypeSigSeedSubFilter   )	constants)PreparedByteRangeDigestPdfByteRangeDigestPdfSignedDataSignatureObjectDocumentTimestamp
BuildProps<   c                   $    e Zd ZdZd Zd ZddZy)SigByteRangeObjectzH
    Internal class to handle the ``/ByteRange`` arrays themselves.
    c                 J    d| _         d | _        d| _        d| _        d| _        y )NFr   )_filled_range_object_offsetfirst_region_lensecond_region_offsetsecond_region_lenselfs    Y/var/www/horilla/myenv/lib/python3.12/site-packages/pyhanko/sign/signers/pdf_byterange.py__init__zSigByteRangeObject.__init__-   s)    $(! !$%!!"    c                 :   | j                   rt        d      | j                  t        d      |j                         }|| _        || _        ||z
  | _        |j                  | j                         | j                  |d        |j                  |       d| _         y )NzOffsets already filledz3Could not determine where to write /ByteRange valueT)	r#   
ValueErrorr$   tellr%   r&   r'   seekwrite_to_stream)r)   stream	sig_startsig_endeofold_seeks         r*   fill_offsetszSigByteRangeObject.fill_offsets4   s    <<566$$,E  ;;= )$+!!$w 	D--.VT*Hr,   Nc                 8   | j                   ?|j                         | _         |j                  d       |j                  dt        z         y dd| j                  | j
                  | j                  fz  }t        |      t        dz   k  sJ |j                  |       y )Ns   []    s   [%d %d %d %d]r   r   )r$   r/   write"BYTE_RANGE_ARR_PLACE_HOLDER_LENGTHr%   r&   r'   len)r)   r2   handlercontainer_refstring_reprs        r*   r1   z"SigByteRangeObject.write_to_streamI   s    $$,(.D%LLLL BBC*%%))&&	. K {#'IA'MMMMLL%r,   NN)__name__
__module____qualname____doc__r+   r7   r1    r,   r*   r!   r!   (   s    #*&r,   r!   c                   0    e Zd ZdZddZed        ZddZy)DERPlaceholderz@
    Internal class to handle placeholders for DER content.
    Nc                 .    d|xs dz  | _         d | _        y )N   0i @  )value_offsets)r)   bytes_reserveds     r*   r+   zDERPlaceholder.__init__^   s    ^8y9
r,   c                 H    | j                   t        d      | j                   S )NzNo offsets available)rK   r.   r(   s    r*   offsetszDERPlaceholder.offsetsb   s"    == 344}}r,   c                     |j                         }|j                  d       |j                  | j                         |j                  d       |j                         }| j                  
||f| _        y y )N   <   >)r/   r:   rJ   rK   )r)   r2   r=   r>   startends         r*   r1   zDERPlaceholder.write_to_streami   sZ    TTZZ Tkkm== !3JDM !r,   Nr@   )rA   rB   rC   rD   r+   propertyrN   r1   rE   r,   r*   rG   rG   Y   s%      'r,   rG   T)frozenc                   t    e Zd ZU dZeed<   	 eed<   	 eed<   	 dedeee	j                  f   fdZdedefd	Zy
)r   a  
    .. versionadded:: 0.7.0

    .. versionchanged:: 0.14.0

        Removed ``md_algorithm`` attribute since it was unused.

    Bookkeeping class that contains the digest of a document that is about to be
    signed (or otherwise authenticated) based on said digest. It also keeps
    track of the region in the output stream that is omitted in the byte range.

    Instances of this class can easily be serialised, which allows for
    interrupting the signing process partway through.
    document_digestreserved_region_startreserved_region_endoutputcms_datac                 l    t        |t              r|}n|j                         }| j                  ||      S )aK  
        Write a DER-encoded CMS object to the reserved region indicated
        by :attr:`reserved_region_start` and :attr:`reserved_region_end` in the
        output stream.

        :param output:
            Output stream to use. Must be writable and seekable.
        :param cms_data:
            CMS object to write. Can be provided as an
            :class:`asn1crypto.cms.ContentInfo` object, or as raw DER-encoded
            bytes.
        :return:
            A :class:`bytes` object containing the contents that were written,
            plus any additional padding.
        )
isinstancebytesdumpfill_reserved_region)r)   r[   r\   	der_bytess       r*   fill_with_cmsz%PreparedByteRangeDigest.fill_with_cms   s1    $ h& I I((;;r,   content_bytesc                 v   t        j                  |      j                         }| j                  }| j                  }||z
  dz
  }t        |      }||kD  rt        d| d| d      |j                  |dz          |j                  |       |j                  d       t        |dz  t        |      z
        }||z   S )aA  
        Write hex-encoded contents to the reserved region indicated
        by :attr:`reserved_region_start` and :attr:`reserved_region_end` in the
        output stream.

        :param output:
            Output stream to use. Must be writable and seekable.
        :param content_bytes:
            Content bytes. These will be padded, hexadecimally encoded and
            written to the appropriate location in output stream.
        :return:
            A :class:`bytes` object containing the contents that were written,
            plus any additional padding.
        r   z8Final ByteRange payload larger than expected: allocated z bytes, but contents required z bytes.r   r   )
binasciihexlifyupperrY   rZ   r<   r   r0   r:   r_   )	r)   r[   rd   content_hexrR   rS   rL   lengthpaddings	            r*   ra   z,PreparedByteRangeDigest.fill_reserved_region   s     &&}5;;=**&&uq[!N"+, -"87,  	EAI 	[!A!+c-.@@Aw&&r,   N)rA   rB   rC   rD   r_   __annotations__intr   r   r	   ContentInforc   ra   rE   r,   r*   r   r   s   sd      
 
<<$)%*@$A<0)'2 )'e )'r,   r   c                   `     e Zd ZdZ ed      fdd fdZddej                  fdefdZ	 xZ
S )	r   a  
    General class to model a PDF Dictionary that has a ``/ByteRange`` entry
    and a another data entry (named ``/Contents`` by default) that will contain
    a value based on a digest computed over said ``/ByteRange``.
    The ``/ByteRange`` will cover the entire file, except for the value of the
    data entry itself.

    .. danger::
        This is internal API.

    :param data_key:
        Name of the data key, which is ``/Contents`` by default.
    :param bytes_reserved:
        Number of bytes to reserve for the contents placeholder.
        If ``None``, a generous default is applied, but you should try to
        estimate the size as accurately as possible.
    z	/ContentsNrL   c                    t         |           ||dz  dk(  rt        d      || _        t	        |      }|x| |<   | _        t               }|x| t        d      <   | _        y )Nr   r   zbytes_reserved must be evenrp   z
/ByteRange)	superr+   r.   data_keyrG   contentsr!   r   
byte_range)r)   rs   rL   rt   ru   	__class__s        r*   r+   zPdfByteRangeDigest.__init__   sk    %.1*<*A:;; !@)11X')
9CCXl#$tr,   Fwriterc              #     K   d|_         |rBt        |t              st        d      |j                  j
                  }|j                          n&t        j                  |      }|j                  |       |j                         }| j                  j                  \  }}| j                  j                  ||||       t        |      }	t!        j"                  |	      }
d}t        |t$              r|j'                         }n	 t)        |      }|9|
j-                  |d|        |
j-                  |||        |j/                          nbt1        |      }|j3                  d       t        j4                  |||
|       |j3                  |       t        j4                  |||
||z
         |
j7                         }t9        |||      }||f}|j;                  ||       y# t        t*        f$ r Y w xY ww)a  
        Generator coroutine that handles the document hash computation and
        the actual filling of the placeholder data.

        .. danger::
            This is internal API; you should use use :class:`.PdfSigner`
            wherever possible. If you *really* need fine-grained control,
            use :class:`~pyhanko.sign.signers.cms_embedder.PdfCMSEmbedder`
            instead.
        Tz4in_place is only meaningful for incremental writers.Nr   )max_read)rX   rY   rZ   )digest_aware_writer^   r   	TypeErrorprevr2   write_in_placer   prepare_rw_output_streamr:   r/   rt   rN   ru   r7   r   r
   Hashr   	getbuffer
memoryviewIOErrorupdaterelease	bytearrayr0   chunked_digestfinalizer   rc   )r)   rw   md_algorithmin_placer[   
chunk_sizer5   r3   r4   md_specmdoutput_buffertemp_bufferdigest_valueprepared_br_digestr\   s                   r*   fillzPdfByteRangeDigest.fill   s    & %)!f&>?J  [[''F!!#226:FLL  kkm!]]22	7$$VYE -\:[[! fg&",,.M *6 2 $
 IImJY/0IImGC01!!##J/KKKNVR)LKK VR#-P{{}4("+ '

 ,V33 ..vx@@5 w' s+   C<G5?G  
CG5 G2/G51G22G5)rA   rB   rC   rD   r   r+   r   DEFAULT_CHUNK_SIZEr   r   __classcell__rv   s   @r*   r   r      sB    $ !) 5 	D 	D **KA!KAr,   r   c                   N     e Zd ZdZej
                  ddfdedee   f fdZ	 xZ
S )r   a  
    Generic class to model signature dictionaries in a PDF file.
    See also :class:`.SignatureObject` and :class:`.DocumentTimestamp`.

    :param obj_type:
        The type of signature object.
    :param subfilter:
        See :class:`.SigSeedSubFilter`.
    :param timestamp:
        The timestamp to embed into the ``/M`` entry.
    :param bytes_reserved:
        The number of bytes to reserve for the signature.
        Defaults to 16 KiB.

        .. warning::
            Since the CMS object is written to the output file as a hexadecimal
            string, you should request **twice** the (estimated) number of bytes
            in the DER-encoded version of the CMS object.
    N	subfilter	timestampc           	          t         |   |       | j                  t        d      |t        d      t        d      t        d      |j                  i       |t        |      | t        d      <   y y )Nrp   z/Typez/Filterz/Adobe.PPKLitez
/SubFilterz/M)rr   r+   r   r   rJ   r   )r)   obj_typer   r   rL   rv   s        r*   r+   zPdfSignedData.__init__Z  sn     	7!8#X.>%?&		
  #+I#6D$  !r,   )rA   rB   rC   rD   r   DEFAULT_SIG_SUBFILTERr   r   r   r+   r   r   s   @r*   r   r   E  s<    . '0&E&E(,7 $7 H%	7 7r,   r   c                   T    e Zd ZU dZeed<   	 dZee   ed<   	 dej                  fdZ
y)r   zy
    Entries in a signature build properties dictionary; see Adobe PDF Signature
    Build Dictionary Specification.
    nameNrevisionreturnc                     t        j                  t        d      t        d| j                  z         i      }| j                  r"t        j
                  | j                        |d<   |S )zn
        Render the build properties as a PDF object.

        :return:
            A PDF dictionary.
        /Name/z/REx)r   DictionaryObjectr   r   r   TextStringObject)r)   propss     r*   as_pdf_objectzBuildProps.as_pdf_object  sT     ((gtyy 9:
 ==#44T]]CE&Mr,   )rA   rB   rC   rD   strrl   r   r   r   r   r   rE   r,   r*   r   r   n  s:    
 I #Hhsm"w77 r,   r   c                   z     e Zd ZdZdej
                  ddddddddf
dee   dedee	   dee
   dee   f
 fdZ xZS )	r   a  
    Class modelling a (placeholder for) a regular PDF signature.

    :param timestamp:
        The (optional) timestamp to embed into the ``/M`` entry.
    :param subfilter:
        See :class:`.SigSeedSubFilter`.
    :param bytes_reserved:
        The number of bytes to reserve for the signature.
        Defaults to 16 KiB.

        .. warning::
            Since the CMS object is written to the output file as a hexadecimal
            string, you should request **twice** the (estimated) number of bytes
            in the DER-encoded version of the CMS object.
    :param name:
        Signer name. You probably want to leave this blank, viewers should
        default to the signer's subject name.
    :param location:
        Optional signing location.
    :param reason:
        Optional signing reason. May be restricted by seed values.
    :params contact_info:
        Optional information from the signer to enable the receiver to contact
        the signer and verify the signature.
    :param app_build_props:
        Optional dictionary containing informations about the computer environment used for signing.
        See :class:`.BuildProps`.
    :param prop_auth_time:
        Optional information representing the number of seconds since signer was last authenticated.
    :param prop_auth_type:
        Optional information about the method of user's authentication
        See :class:`.SigAuthType`.
    Nr   r   app_build_propsprop_auth_timeprop_auth_typec                    t         |   t        d      |||
       |rt        |      | t        d      <   |rt        |      | t        d      <   |rt        |      | t        d      <   |rt        |      | t        d      <   |r:t	        j
                  t        d      |j                         i      | t        d      <   |r!t	        j                  |      | t        d	      <   |	r|	j                  | t        d
      <   y y )Nz/Sig)r   r   r   rL   r   z	/Locationz/Reasonz/ContactInfoz/Appz/Prop_Buildz/Prop_AuthTimez/Prop_AuthType)	rr   r+   r   r   r   r   r   NumberObjectrJ   )r)   r   r   r   locationreasoncontact_infor   r   r   rL   rv   s              r*   r+   zSignatureObject.__init__  s     	f%)	 	 	
 &0&6D'"#*4X*>D+&'(26(:D)$%-7-ED.)*,3,D,D&!?#@#@#BC-D-() /6/C/C0D*+, /=/C/CD*+, r,   )rA   rB   rC   rD   r   r   r   r   r   r   rm   r   r+   r   r   s   @r*   r   r     s    !J )-&/&E&E04(,04%DH%%D $%D "*-%D !%D !-%D %Dr,   r   c                   $     e Zd ZdZd fd	Z xZS )r   a  
    Class modelling a (placeholder for) a regular PDF signature.

    :param bytes_reserved:
        The number of bytes to reserve for the signature.
        Defaults to 16 KiB.

        .. warning::
            Since the CMS object is written to the output file as a hexadecimal
            string, you should request **twice** the (estimated) number of bytes
            in the DER-encoded version of the CMS object.
    c                 X    t         |   t        d      t        j                  |       y )Nz/DocTimeStamp)r   r   rL   )rr   r+   r   r   ETSI_RFC3161)r)   rL   rv   s     r*   r+   zDocumentTimestamp.__init__  s)    o.&33) 	 	
r,   rT   )rA   rB   rC   rD   r+   r   r   s   @r*   r   r     s    
 
r,   r   ).rD   rf   dataclassesr   r   ior   typingr   r   r   
asn1cryptor	   cryptography.hazmat.primitivesr
   pyhanko.pdf_utilsr   r   pyhanko.pdf_utils.genericr   r   r   $pyhanko.pdf_utils.incremental_writerr   pyhanko.pdf_utils.writerr   pyhanko.sign.generalr   r   fieldsr   r    r   __all__r;   	PdfObjectr!   rG   r   r   r   r   r   r   r   rE   r,   r*   <module>r      s   
  !   & &  1 + D D I 6 I 2 
 &( ".&** .&b'W&& '4 $b' b' b'JiA11 iAX&7& &7R $     FIDm IDX
 
r,   