U
    <gZ                  	   @   s2  d dl Z d dlZd dlmZ d dlmZmZmZmZm	Z	m
Z
 d dlmZmZ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mZ d	d
lmZmZmZmZmZmZm Z m!Z! d	dl"m#Z#m$Z$ d	dl%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/ ddl0m1Z1 ddl2m3Z3 ddl4m5Z5 dddddgZ6e-e/de/ddddd e.j7d!Z8e9d"d#d$d%d&d'gZ:G d(d) d)eZ;G d*d dZ<e5e=ee= d+d,d-Z>d.d/ Z?d0d1 Z@ejAejBd2d3d4ZCe	ejBe=f d5d6d7ZDe:e<fe1eeE e
e< d8d9dZFG d:d; d;e#ZGd"d dejHfe3eEd<d=dZIdS )>    N)compare_digest)AnyDict	FrozenSetOptionalTupleType)algoscmscore)VOID)hasheshmackeywrap)hkdf)genericmisc   )CMSStructuralErrorMultivaluedAttributeErrorNonexistentAttributeErrorValueErrorWithMessagebyte_range_digestfind_unique_cms_attributeget_pyca_cryptography_hashsimple_cms_attribute)PdfByteRangeDigestPreparedByteRangeDigest)CMSAlgorithmProtectionErrorDisallowedAlgorithmError)validate_algorithm_protection)extract_contents   )DeveloperExtensionDevExtensionMultivalued)pdf_name)PdfFileReader)BasePdfFileWriter   )PdfMacIntegrityInfoPdfMacTokenHandlervalidate_pdf_macadd_standalone_macISO32004ALLOWED_MD_ALGSz/ISO_z/2.0i}  z:2024z'https://www.iso.org/standard/45877.htmlF)Zprefix_namebase_versionZextension_levelZextension_revisionurlZcompare_by_levelZmultivaluedsha256sha3_256sha384sha3_384sha512sha3_512c                   @   s   e Zd ZdS )PdfMacValidationErrorN)__name__
__module____qualname__ r;   r;   B/tmp/pip-unpacked-wheel-w101_d3s/pyhanko/pdf_utils/crypt/pdfmac.pyr7   J   s   r7   c                   @   s|  e Zd ZdZeddiZdd Zee	e	e
dddZeefe	e	ejee
 d	d
dZeedddZee	e	e	dddZe	ejdddZeee	ejf dddZe	ee	 ee	e	f dddZeje	eje	ejdddZe	e	e	ddd Zd!d"e	ee	 eejd#d$d%Zeje	d&d'd(Z eje!j"d)d*d+Z#ejd,d-d.Z$eje%d/d0d1Z&eje	ee	 d2d3d4Z'd5S )6r*   a:  
    Internal utility class to create and validate PDF MAC tokens.

    .. warning::
        This is a class to simplify local overrides for creating test documents
        with various defects.

        Instances of this class should never be created or manipulated directly
        during regular operation.
    	algorithmr1   c                C   s   || _ || _d S Nmac_kekmd_algorithm)selfr@   rA   r;   r;   r<   __init__\   s    zPdfMacTokenHandler.__init__file_encryption_keykdf_saltrA   c                 C   s   |  ||}| ||dS )Nr?   )_derive_mac_kek)clsrE   rF   rA   r@   r;   r;   r<   from_key_mat`   s    zPdfMacTokenHandler.from_key_matrE   rF   	auth_dataallowed_mdsc           	      C   s\   |d }|d j }|dkr"td|d }|d j }||krLt|tjdd| j|||dS )	Nmac_algorithmr=   r1   z:Only HMAC-SHA256 is currently supported for PDF MAC tokensdigest_algorithmT)Zoid_typeZ	permanentrD   )nativeNotImplementedErrorr   r	   ZDigestAlgorithmIdrI   )	rH   rE   rF   rK   rL   Zmac_algo_objZmac_algoZdigest_algo_objZmd_algor;   r;   r<   for_validationg   s&    	

z!PdfMacTokenHandler.for_validation)include_signature_digestreturnc                 C   s8   t t| j }| j||r"|nd dd}t| S )NT)document_digestsignature_digestdry_run)r   Hashr   rA   finalizebuild_pdfmac_tokenlendump)rB   rR   Z
dummy_hashZdummy_tokenr;   r;   r<   determine_token_size   s    
z'PdfMacTokenHandler.determine_token_size)rE   rF   rS   c                 C   s    t jt d|dd}||S )N    s   PDFMAC)r=   lengthsaltinfo)r   ZHKDFr   SHA256Zderive)rH   rE   rF   kdfr;   r;   r<   rG      s    z"PdfMacTokenHandler._derive_mac_kek)message_digestrS   c                 C   s@   t | jt d| jid}t tddtd|td|gS )Nr=   )rM   rN   content_typepdf_mac_integrity_inforc   Zcms_algorithm_protection)r
   ZCMSAlgorithmProtectionmac_algo_identDigestAlgorithmrA   CMSAttributesr   )rB   rc   Zalgo_protectionr;   r;   r<   _format_auth_attrs   s      z%PdfMacTokenHandler._format_auth_attrs)rV   rS   c              	   C   sb   |rt d}n
td}tj| j|d}td|t	ddit
ddid}|td|ifS )	Nr]   )wrapping_keyZkey_to_wrapr   r=   pdf_mac_wrap_kdfaes256_wrap)versionencrypted_keykey_derivation_algorithmkey_encryption_algorithmpwri)bytessecretsZtoken_bytesr   Zaes_key_wrapr@   r
   PasswordRecipientInfor	   ZKdfAlgorithmZKeyEncryptionAlgorithmRecipientInfo)rB   rV   mac_keyrn   rq   r;   r;   r<   _get_mac_keying_info   s*    

  z'PdfMacTokenHandler._get_mac_keying_info)rT   rU   rS   c           	      C   s^   d|i}|d k	r||d< d|d< t |}| }t| j}t|}|| | }||fS )Ndata_digestrU   r   rm   )r)   r[   r   rA   r   rW   updaterX   )	rB   rT   rU   Zmessage_kwargsmessagemessage_bytesmd_specZmd_funrc   r;   r;   r<   _format_message   s    


z"PdfMacTokenHandler._format_message)recipient_infor{   
auth_attrsmacrS   c                 C   sD   t d|gt ddit d| jit dt|d||dS )Nr   r=   r1   re   rd   content)rm   recipient_infosrM   rN   encap_content_infor   r   )r
   AuthenticatedDataHmacAlgorithmrg   rA   ZEncapsulatedContentInfor   ParsableOctetString)rB   r~   r{   r   r   r;   r;   r<   _format_auth_data   s     z$PdfMacTokenHandler._format_auth_data)rv   data_to_macrS   c                 C   s$   t j|t d}|| | S )N)keyr=   )r   HMACr   ra   ry   rX   )rB   rv   r   Zhmac_funr;   r;   r<   compute_mac   s    
zPdfMacTokenHandler.compute_macFrV   )rT   rU   rV   rS   c                C   sb   | j |d\}}| ||\}}| |}| j||  d}	| j||||	d}
td|
dS )Nr   )rv   r   )r~   r{   r   r   authenticated_datar   )	rw   r}   ri   r   untagr[   r   r
   ContentInfo)rB   rT   rU   rV   rv   rir{   rc   r   r   Zauthed_datar;   r;   r<   rY     s&     
 
z%PdfMacTokenHandler.build_pdfmac_token)
recp_infosrS   c                 C   s   d }z|\}|j }W n tk
r(   Y nX t|tjs>td|d }|tks\|d jdkrdtd|d d }|jdkrtd|j	d	|d
 j}zt
j| j|d}W n t
jk
r   tdY nX |S )NzWPDF MAC requires exactly one recipientInfo, which must be of PasswordRecipientInfo typero   r=   rk   z_PDF MAC tokens must have their key derivation algorithm explicitly identified as pdfMacWrapKdf.rp   rl   zPPDF MAC only supports unpadded 256-bit AES key wrapping for key encryption; not .rn   )rj   Zwrapped_keyzFailed to unwrap MAC key)Zchosen
ValueError
isinstancer
   rt   r7   r   rO   rP   dottedr   Zaes_key_unwrapr@   ZInvalidUnwrap)rB   r   rq   Zrecprb   Zkea_objrn   rv   r;   r;   r<   _retrieve_mac_key  s:    


 
z$PdfMacTokenHandler._retrieve_mac_key)attrsencap_contentc              	   C   sp   t | j}t|}|t| | }z t|d}|j|krHt	dW n  t
tfk
rj   t	dY nX d S )Nrc   zMValue of messageDigest attribute does not match hash of encapsulated content.zcMessage digest not found in authenticated attributes, or multiple messageDigest attributes present.)r   rA   r   rW   ry   rr   rX   r   rO   r7   r   r   )rB   r   r   r|   Zmdrc   Zclaimed_message_digestr;   r;   r<   _validate_message_digestD  s"    

 
z+PdfMacTokenHandler._validate_message_digest)rK   c              
   C   s~   |d }t | zt|d |d |d d W n2 tk
r^ } ztd|j |W 5 d }~X Y nX |d d }| j||d d S )	Nr   rN   rM   )Zclaimed_signature_algorithm_objZclaimed_digest_algorithm_objZclaimed_mac_algorithm_objz%CMS alg protection validation error: r   r   )r   )_validate_content_type_attrr    r   r7   failure_messager   )rB   rK   r   eZint_info_objr;   r;   r<   _validate_auth_attrsZ  s"    
z'PdfMacTokenHandler._validate_auth_attrs)rK   rS   c           	   
   C   s   |d }|t k	rtd|d }|d }| |}| j||  d}t||d js`tdz| | W n2 t	k
r } ztd|j
 |W 5 d }~X Y nX |d	 d
 j}|dkrtd|d	 d jS )Nunauth_attrsz5PDF MAC tokens cannot have unauthenticated attributesr   r   )r   r   zPDF MAC token has invalid MACzCMS structural error: r   rd   re   z_The content type of the encapsulated content in a PDF MAC token must be id-pdfMacIntegrityInfo.r   )r   r7   r   r   r   r[   r   rO   r   r   r   parsed)	rB   rK   r   r   r   rv   Zcomputed_macr   Zeci_ctr;   r;   r<   #_validate_and_extract_encap_contentq  s8    
 
z6PdfMacTokenHandler._validate_and_extract_encap_contentrK   rT   rU   c                C   s   |  |}t||| d S r>   )r    _validate_pdf_mac_integrity_info)rB   rK   rT   rU   r   r;   r;   r<   validate_pdfmac_token_cms  s    
  z,PdfMacTokenHandler.validate_pdfmac_token_cmsN)(r8   r9   r:   __doc__r
   r   rf   rC   classmethodrr   strrI   r.   r   r   rQ   boolintr\   rG   rh   ri   r   ru   rw   r   r}   r   r   r   rY   ZRecipientInfosr   r   r   r   r   r)   r   r   r;   r;   r;   r<   r*   N   sp        

' +)int_inforT   rU   c                 C   sf   | d j }||krtd| d }|d kr<|tk	rbtdn&|j }|d krRtd||krbtdd S )Nrx   z;Document digest does not match value in PdfMacIntegrityInforU   z;PdfMacIntegrityInfo contains an unexpected signature digestz6Could not find signature digest in PdfMacIntegrityInfoz<Signature digest does not match value in PdfMacIntegrityInfo)rO   r7   r   )r   rT   rU   Zclaimed_data_digestZsig_digest_objZclaimed_signature_digestr;   r;   r<   r     s(    
r   c              	   C   sN   z(t | d}|jdkr&td|jW n  ttfk
rH   tdY nX d S )Nrd   re   zRThe content type attribute of a PDF MAC token must be id-pdfMacIntegrityInfo, not z`Content type not found in authenticated attributes, or multiple content-type attributes present.)r   rO   r7   r   r   r   )r   rd   r;   r;   r<   r     s    


r   c           	      C   s   z|  d}W n tk
r&   d }Y nX t|tjs<tdt|dkr|\}}}}d| d }|dkr|| |kr||| | krd S tdd S )N
/ByteRangez(No sensible /ByteRange found in AuthCode   r"   r   z;PDF MAC token must have /ByteRange covering the entire file)raw_getKeyErrorr   r   ZArrayObjectr7   rZ   )	Zpdf_dictfile_lenpayload_len
byte_rangeZo1l1Zo2l2Zvalue_lit_lenr;   r;   r<   _validate_byte_range  s&    

r   )ac_dictrS   c              	   C   s   z|  dj}W n  ttfk
r0   tdY nX tj|}t|}t|	 }||krptd| d| dt
| || |S )N/MACz'Failed to retrieve standalone MAC valuez<Standalone MACs must not have trailing CMS data: payload is z bytes long, but token is z bytes.)r   original_bytesr   AttributeErrorr7   r
   r   loadrZ   r[   r   )r   r   Z	mac_bytesmac_cir   Z	token_lenr;   r;   r<   _extract_standalone_mac  s    r   )rS   c              
   C   s   zt | }W n$ tttjfk
r0   tdY nX tj|}t	|}t
| || d }|d jdkr|d }t	|d dkr|d d }|d krtdzt|d	 d
}W n  ttfk
r   tdY nX ||d jfS )Nz%Failed to retrieve signature contentsrd   Zsigned_datar   Zsigner_infosr(   r   zQSignature dictionary must contain a SignedData message with exactly 1 signerInfo.Zunsigned_attrsZpdf_mac_dataz;Signature must have exactly 1 pdfMacData unsigned attribute	signature)r!   r   r   r   PdfReadErrorr7   r
   r   r   rZ   r   rO   r   r   r   )sig_dictr   Z	sig_bytesZsig_cir   Zsigner_infosdr   r;   r;   r<   _extract_mac_in_sig  s4     
r   )readerrL   handler_clsc              
   C   sN  z| j d}W n tk
r(   d }Y nX t|tjr>tdt|tjsRtdd}d}z4|d}t|tjr|dkrd}n|dkrd}W n tk
r   Y nX | j	
d	tj}|rt||}|d
 }	d }
n|rXz|d}W n< tjk
r   tdY n tk
r    tdY nX | }t|tjs@tdt||\}}
|d
 }	ntd|d jdkrxtd| j}|d k	st|d }|d d j }t| j	|	|d\}}|
d k	rtt|}||
 | }nd }z| }W n0 tjk
r& } ztd|W 5 d }~X Y nX |j|  |||dj!|||d d S )N	/AuthCodez&AuthCode dictionary cannot be indirectz$Failed to locate AuthCode dictionaryF/MACLocation/StandaloneTz/AttachedToSigr   r   z
/SigObjRefz7Value of /SigObjRef entry must be an indirect referencez"/AttachedToSig requires /SigObjRefz)/SigObjRef does not point to a dictionaryz Failed to locate MAC in documentrd   r   z0MAC tokens must be of CMS type AuthenticatedDatar   rN   r=   )r   rA   zError retrieving saltrJ   r   )"Ztrailer_viewr   r   r   r   ZIndirectObjectr7   DictionaryObjectZ
NameObjectstreamseekosSEEK_ENDr   Zget_value_as_referenceZIndirectObjectExpectedZ
get_objectr   rO   Zsecurity_handlerAssertionErrorlowerr   r   rW   r   ry   rX   Zget_kdf_saltr   r   rQ   Zget_file_encryption_keyr   )r   rL   r   r   Zis_standaloneZis_in_signatureZmac_locationr   r   r   Zsignature_valueZsig_refr   shrK   rA   _rT   Zsig_mdrU   r_   r   r;   r;   r<   r+   &  s    



  



c                       s   e Zd Z fddZ  ZS )StandalonePdfMacc                   s$   t  jtd|d td| d< d S )Nr   )Zdata_keybytes_reservedr   r   )superrC   r%   )rB   r   	__class__r;   r<   rC     s
     zStandalonePdfMac.__init__)r8   r9   r:   rC   __classcell__r;   r;   r   r<   r   ~  s   r   )wrA   c                 C   s   | j |d}|jdd}td| d}| td| |j| |j|||d}t|\}	}
|j|	j	d d}|	j
|
|d	 t||
S )
N)rA   F)rR   r"   )r   r   )rA   in_place
chunk_sizeoutput)rT   rU   )Zcms_data)Z_init_mac_handlerr\   r   Zset_custom_trailer_entryr%   fillrA   nextrY   rT   Zfill_with_cmsr   Zfinalise_output)r   rA   r   r   r   handlerZtok_sizeZmac_dictZ
cms_writerZprepared_br_digestZ
res_outputZpdfmac_tokenr;   r;   r<   r,     s(    
)Jr   rs   r   r   typingr   r   r   r   r   r   Z
asn1cryptor	   r
   r   Zasn1crypto.corer   Zcryptography.hazmat.primitivesr   r   Z"cryptography.hazmat.primitives.kdfr   Zpyhanko.pdf_utilsr   r   Zsign.generalr   r   r   r   r   r   r   r   Zsign.signers.pdf_byteranger   r   Zsign.validation.errorsr   r   Zsign.validation.generic_cmsr    Zsign.validation.pdf_embeddedr!   
extensionsr#   r$   r%   r   r&   writerr'   Z_iso32004_asn1r)   __all__ZALWAYSr-   	frozensetr.   r7   r*   rr   r   r   r   r   r   r   r   r   r+   r   ZDEFAULT_CHUNK_SIZEr,   r;   r;   r;   r<   <module>   s    (
	  \$X
