U
    g\                  
   @   s.  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 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mZ ddlmZ ddlmZm Z m!Z! ddl"m#Z#m$Z$m%Z%m&Z& ddl'm(Z(m)Z) ddl*m+Z+ ddl,m-Z-m.Z.m/Z/ ddddddgZ0e 1e2Z3e	de.dZ4G dd deZ5eej6ej6dZ7dd  Z8eej9ej9dZ:d!d" Z;ee<d#d$d%Z=ej>ee?d&d'dZ@eee( d(d)dZAeG d*d+ d+ZBe(d,d-d.ZCeBd/d0d1ZDd9e(e5ee< ee ee ee+ eEe-d3d4dZFejGd5d6dZHd:ejGed7d8dZIdS );    N)	dataclass)datetime)Enum)IteratorOptionalTypeVar)cms)pdf)ValidationContext)CertRevTrustPolicyRevocationCheckingPolicyRevocationCheckingRule)PdfFileReader   )
DiffPolicy)MultivaluedAttributeErrorNonexistentAttributeErrorfind_unique_cms_attribute   )DocumentSecurityStore)NoDSSFoundErrorSignatureValidationErrorValidationInfoReadingError)async_validate_cms_signaturecms_basic_validationcollect_signer_attr_statusvalidate_tst_signed_data)EmbeddedPdfSignaturereport_seed_value_validation)KeyUsageConstraints)PdfSignatureStatusSignatureStatusTimestampSignatureStatusRevocationInfoValidationTypeapply_adobe_revocation_inforetrieve_adobe_revocation_infoget_timestamp_chain async_validate_pdf_ltv_signatureestablish_timestamp_trust
StatusType)boundc                   @   s(   e Zd ZdZdZdZdZedd ZdS )r#   zP
    Indicates a validation profile to use when validating revocation info.
    adobeZpadesz	pades-ltac                 C   s   t dd | D S )Nc                 s   s   | ]}|j V  qd S )N)value).0m r/   ?/tmp/pip-unpacked-wheel-owvgwkas/pyhanko/sign/validation/ltv.py	<genexpr>U   s     z8RevocationInfoValidationType.as_tuple.<locals>.<genexpr>)tuple)clsr/   r/   r0   as_tupleS   s    z%RevocationInfoValidationType.as_tupleN)	__name__
__module____qualname____doc__ADOBE_STYLEPADES_LT	PADES_LTAclassmethodr4   r/   r/   r/   r0   r#   ;   s   )Zee_certificate_ruleZintermediate_ca_cert_rulec                  K   s   t f dti| S Nrevocation_checking_policy)r   &DEFAULT_LTV_INTERNAL_REVO_CHECK_POLICYkwargsr/   r/   r0   !_default_ltv_internal_revo_policy^   s
    rB   c                  K   s   t f dti| S r=   )r   %STRICT_LTV_INTERNAL_REVO_CHECK_POLICYr@   r/   r/   r0    _strict_ltv_internal_revo_policyk   s
    rD   )	timestampvalidation_context_kwargsc                 C   s   d|d< | |d< | dd }| dd}|d krl|dd }|rX|dkrXtt|}q~|dkr~t|d}n|jjs~t|d}||d< d S )	NFallow_fetchingmomentrevinfo_policyretroactive_revinforevocation_modez	soft-failrJ   )	getpopr   r   Zfrom_legacyrB   r>   Z	essentialrD   )rE   rF   rI   retroactiveZ	legacy_rmr/   r/   r0   _strict_vc_context_kwargsr   s,     rP   )tst_signed_datavalidation_contextexpected_tst_imprintc                    sD   t | ||I dH }tf |}|jr(|js@td|  td|S )a  
    Wrapper around :func:`validate_tst_signed_data` for use when analysing
    timestamps for the purpose of establishing a timestamp chain.
    Its main purpose is throwing/logging an error if validation fails, since
    that amounts to lack of trust in the purported validation time.

    This is internal API.

    :param tst_signed_data:
        The ``SignedData`` value to validate; must encapsulate a ``TSTInfo``
        value.
    :param validation_context:
        The validation context to apply to the timestamp.
    :param expected_tst_imprint:
        The expected message imprint for the ``TSTInfo`` value.
    :return:
        A :class:`.TimestampSignatureStatus` if validation is successful.
    :raises:
        :class:`SignatureValidationError` if validation fails.
    Nz0Could not validate embedded timestamp token: %s.z\Could not establish time of signing, timestamp token did not validate with current settings.)r   r"   ZvalidZtrustedloggerwarningsummaryr   )rQ   rR   rS   Ztimestamp_status_kwargstimestamp_statusr/   r/   r0   r(      s      

)readerreturnc                 C   s   t dd t| jS )a:  
    Get the document timestamp chain of the associated reader, ordered
    from new to old.

    :param reader:
        A :class:`.PdfFileReader`.
    :return:
        An iterable of
        :class:`~pyhanko.sign.validation.pdf_embedded.EmbeddedPdfSignature`
        objects representing document timestamps.
    c                 S   s   | j dd dkS )Nz/Typez/DocTimeStamp)Z
sig_objectrM   )sigr/   r/   r0   <lambda>       z%get_timestamp_chain.<locals>.<lambda>)filterreversedZembedded_signatures)rX   r/   r/   r0   r&      s    c                   @   s2   e Zd ZU eed< ee ed< eed< eed< dS )_TimestampTrustData
latest_dtsearliest_ts_statusts_chain_lengthcurrent_signature_vc_kwargsN)	r5   r6   r7   r   __annotations__r   r"   intdictr/   r/   r/   r0   r_      s   
r_   )emb_timestampc                 C   s`   z$| j | j}t|}||W S  tk
rZ   |dd |dd tf | Y S X d S )Ncrlsr/   ocsps)	rX   Zget_historical_resolversigned_revisionr   read_dssas_validation_contextr   
setdefaultr
   )rg   rF   Zhist_resolverdssr/   r/   r0   _instantiate_ltv_vc   s    
ro   )rY   c           
         s   t | }t|}|}d }d}d }t|D ]H\}}|j|k r> qr| }	t|j||	I d H }t|j| t	||}q(t
|||d |dS )Nr   )r`   ra   rb   rc   )r&   rf   	enumeraterj   compute_digestr(   signed_datarP   rE   ro   r_   )
rX   bootstrap_validation_contextrF   until_revisionZ
timestamps
current_vcZ	ts_statusZts_countrg   external_digestr/   r/   r0   _establish_timestamp_trust_lta   s:    
  
  rx   F)embedded_sigvalidation_typerF   rt   diff_policykey_usage_settings	skip_diffrY   c	                    s  t |pi }	|	dd |	dd |	d }
|rVt|
d|	d< |dk	rt|
d|d< n4d|	kr|	dt|
d |dk	r|dt|
d | j}|tjkrd}|ptf |	}n6t	|}|dkr|j
|	dd	}n|}|j|  |   |   d}d}d
}|tjkrt|||	| jdI dH }|j}|j}	|jrDt|j|	}|jdkrd|tjkrdtd|tjks|jdkst|j}|j}| j}|dk	r| j}|dk	stt|||I dH }|dk	st|j}||	d< |dk	r||d< n|tjkr|dkrtd|dkr"tdt|j|	 d}|tjkrt | j!\}}||	d< ||	d< tf |	}|dk	r||d< ||d< tf |}nf|tjkr|dk	st|
|	}|dk	r|
|}n,|dk	stt||	}|dk	rt||}|dk	s|tjkrN|dk	r|}n|dk	s&t|j"}t#|t$|d|jid}|I dH }n|}| j%||d | & }|'|j|d t()|}t*| j"| j+|||dI dH }t,| |d dd |dk	r|j| j- |'t.| j/| j0|| j!d dI dH  t(f |S )a   
    .. versionadded:: 0.9.0

    Validate a PDF LTV signature according to a particular profile.

    :param embedded_sig:
        Embedded signature to evaluate.
    :param validation_type:
        Validation profile to use.
    :param validation_context_kwargs:
        Keyword args to instantiate
        :class:`.pyhanko_certvalidator.ValidationContext` objects needed over
        the course of the validation.
    :param ac_validation_context_kwargs:
        Keyword arguments for the validation context to use to
        validate attribute certificates.
        If not supplied, no AC validation will be performed.

        .. note::
            :rfc:`5755` requires attribute authority trust roots to be specified
            explicitly; hence why there's no default.
    :param bootstrap_validation_context:
        Validation context used to validate the current timestamp.
    :param force_revinfo:
        Require all certificates encountered to have some form of live
        revocation checking provisions.
    :param diff_policy:
        Policy to evaluate potential incremental updates that were appended
        to the signed revision of the document.
        Defaults to
        :const:`~pyhanko.sign.diff_analysis.DEFAULT_DIFF_POLICY`.
    :param key_usage_settings:
        A :class:`.KeyUsageConstraints` object specifying which key usages
        must or must not be present in the signer's certificate.
    :param skip_diff:
        If ``True``, skip the difference analysis step entirely.
    :return:
        The status of the signature.
    rG   TrJ   FrL   rI   NrK   )Zinclude_revinfor   )rF   ru   z>Purported PAdES-LTA signature does not have a timestamp chain.r   rH   zlPAdES-LTA signature requires separate timestamps protecting the signature & the rest of the revocation info.z+LTV signatures require a trusted timestamp.ri   rh   rE   )Z
status_clsrR   status_kwargs)r{   r}   )Zsigner_reported_dtZtimestamp_validity)Z
raw_digestrR   r~   r|   Zvalidation_path)Ztimestamp_foundsigned_attrs)Zsd_attr_certificatessigner_certrR   Zsd_signed_attrs)1rf   rm   rB   rD   rX   r#   r9   r
   r   rk   rl   Zcertificate_registryZregister_multipleZ
load_certsrr   Zcompute_tst_digestrx   rj   rb   rc   r`   ro   ra   r;   r   r:   AssertionErrorZattached_timestamp_datatst_signature_digestr(   rE   rP   r%   signer_infors   r   r"   Zcompute_integrity_infoZsummarise_integrity_infoupdater    Zdefault_usage_constraintsr   rw   r   Zother_embedded_certsr   Zembedded_attr_certsr   )ry   rz   rF   rt   Zac_validation_context_kwargsZforce_revinfor{   r|   r}   Z	vc_kwargsrO   rX   rn   rv   Zearliest_good_timestamp_str`   rb   Zts_trust_datarQ   r   Zsignature_poeZstored_ac_vcri   rh   Z	stored_vcZts_to_validateZts_status_cororW   r~   r/   r/   r0   r'     s^   4


 
 	
  









 
   

	)r   c              
   C   sl   zt | d d}W n0 ttfk
rB } ztd|W 5 d}~X Y nX t|d pPd}t|d p`d}||fS )a'  
    Retrieve Adobe-style revocation information from a ``SignerInfo`` value,
    if present.

    Internal API.

    :param signer_info:
        A ``SignerInfo`` value.
    :return:
        A tuple of two (potentially empty) lists, containing OCSP
        responses and CRLs, respectively.
    r   Zadobe_revocation_info_archivalz@No revocation info archival attribute found, or multiple presentNZocspr/   Zcrl)r   r   r   r   list)r   Zrevinfoeri   rh   r/   r/   r0   r%   D  s     )r   rY   c                 C   s(   |pi }t | \}}tf ||d|S )ag  
    Read Adobe-style revocation information from a CMS object, and load it
    into a validation context.

    :param signer_info:
        Signer info CMS object.
    :param validation_context_kwargs:
        Extra kwargs to pass to the ``__init__`` function.
    :return:
        A validation context preloaded with the relevant revocation information.
    )ri   rh   )r%   r
   )r   rF   ri   rh   r/   r/   r0   r$   _  s     )NNNFNNF)N)JloggingZdataclassesr   r   enumr   typingr   r   r   Z
asn1cryptor   r	   Zasn1_pdfZpyhanko_certvalidatorr
   Z!pyhanko_certvalidator.policy_declr   r   r   Zpyhanko.pdf_utils.readerr   Zdiff_analysisr   Zgeneralr   r   r   rn   r   errorsr   r   r   Zgeneric_cmsr   r   r   r   Zpdf_embeddedr   r   settingsr   statusr    r!   r"   __all__	getLoggerr5   rT   r)   r#   ZCHECK_IF_DECLAREDr?   rB   ZCRL_OR_OCSP_REQUIREDrC   rD   rf   rP   Z
SignedDatabytesr(   r&   r_   ro   rx   boolr'   Z
SignerInfor%   r$   r/   r/   r/   r0   <module>   s   

 &+0         - 