
     hK                        d Z 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
 ddlmZmZmZmZ ddlmZ ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlT ddlmZ g dZ ej        e           Z! G d de"          Z# G d de#          Z$ G d de#          Z%d Z& G d de'          Z( G d de"          Z)d Z*d Z+dej,        dej-        fdZ.	 d?dej,        dej/        fdZ0dej,        d e
ej1        ej2        f         fd!Z3d"e
ej4        ej5        f         dej,        de6fd#Z7 G d$ d%e"          Z8 G d& d'e8          Z9de
ej:                 fd(Z;	 d@de
ej:        ef         fd*Z<d+ede=fd,Z>	 d@d-ej?        fd.Z@dej,        d/e=dej?        fd0ZA ed12           G d3 d4                      ZBd5ejC        fd6ZDd7 ZEd8ejF        dejG        fd9ZHd8ejF        deBfd:ZIejJ        fd;ed<eeK         d=e=de	eKeLf         fd>ZMdS )Aa  
General tools related to Cryptographic Message Syntax (CMS) signatures,
not necessarily to the extent implemented in the PDF specification.

CMS is defined in :rfc:`5652`. To parse CMS messages, pyHanko relies heavily on
`asn1crypto <https://github.com/wbond/asn1crypto>`_.
    N)	dataclass)IOIterableListTupleUnion)algoscmstspx509)SignedDigestAlgorithm)hashesserialization)padding)RSAPublicKey)	Prehashed)*)misc)simple_cms_attributefind_cms_attributefind_unique_cms_attributeNonexistentAttributeErrorMultivaluedAttributeErrorSigningErrorUnacceptableSignerErrorSignedDataCertsextract_signer_infoextract_certificate_infoget_cms_hash_algo_for_mechanismget_pyca_cryptography_hash&get_pyca_cryptography_hash_for_signingoptimal_pss_paramsprocess_pss_paramsas_signing_certificateas_signing_certificate_v2match_issuer_serialcheck_ess_certidCMSExtractionErrorbyte_range_digestValueErrorWithMessageCMSStructuralErrorload_cert_from_pemderload_certs_from_pemderload_certs_from_pemder_dataload_private_key_from_pemder!load_private_key_from_pemder_datac                   "     e Zd ZdZ fdZ xZS )r*   z
    Value error with a failure message attribute that can be conveniently
    extracted, instead of having to rely on extracting exception args
    generically.
    c                 r    t          |          | _        t                                          |           d S N)strfailure_messagesuper__init__)selfr5   	__class__s     P/var/www/html/Sam_Eipo/venv/lib/python3.11/site-packages/pyhanko/sign/general.pyr7   zValueErrorWithMessage.__init__B   s1    "?33)))))    )__name__
__module____qualname____doc__r7   __classcell__r9   s   @r:   r*   r*   ;   sB         * * * * * * * * *r;   r*   c                       e Zd ZdZdS )r+   z!Structural error in a CMS object.Nr<   r=   r>   r?    r;   r:   r+   r+   G   s        ++++r;   r+   c                       e Zd ZdS )r(   Nr<   r=   r>   rD   r;   r:   r(   r(   K           Dr;   r(   c                 V    t          j        t          j        |           |fd          S )a  
    Convenience method to quickly construct a CMS attribute object with
    one value.

    :param attr_type:
        The attribute type, as a string or OID.
    :param value:
        The value.
    :return:
        A :class:`.cms.CMSAttribute` object.
    )typevalues)r
   CMSAttributeCMSAttributeType)	attr_typevalues     r:   r   r   O   s1     %i00UHEE  r;   c                       e Zd ZdS )r   NrF   rD   r;   r:   r   r   `   rG   r;   r   c                       e Zd ZdS )r   NrF   rD   r;   r:   r   r   d   rG   r;   r   c                     d}| r3| D ]0}|d         j         |k    r|t          d|d          |d         }1||S t          d| d          )a  
    Find and return CMS attribute values of a given type.

    .. note::
        This function will also check for duplicates, but not in the sense
        of multivalued attributes. In other words: multivalued attributes
        are allowed; listing the same attribute OID more than once is not.

    :param attrs:
        The :class:`.cms.CMSAttributes` object.
    :param name:
        The attribute type as a string (as defined in ``asn1crypto``).
    :return:
        The values associated with the requested type, if present.
    :raise NonexistentAttributeError:
        Raised when no such type entry could be found in the
        :class:`.cms.CMSAttributes` object.
    :raise CMSStructuralError:
        Raised if the given OID occurs more than once.
    NrI   z
Attribute z was duplicatedrJ   zUnable to locate attribute .)nativer+   r   )attrsnamefound_valuesattrs       r:   r   r   h   s    , L . 	. 	.DF|"d**+,<T<<<    $H~'(Md(M(M(MNNNr;   c                     t          | |          }t          |          dk    r#t          d| dt          |           d          |d         S )a   
    Find and return a unique CMS attribute value of a given type.

    :param attrs:
        The :class:`.cms.CMSAttributes` object.
    :param name:
        The attribute type as a string (as defined in ``asn1crypto``).
    :return:
        The value associated with the requested type, if present.
    :raise NonexistentAttributeError:
        Raised when no such type entry could be found in the
        :class:`.cms.CMSAttributes` object.
    :raise MultivaluedAttributeError:
        Raised when the attribute's cardinality is not 1.
       zExpected single-valued z attribute, but found z valuesr   )r   lenr   )rT   rU   rJ   s      r:   r   r      sk       t,,F
6{{a'$d $ $6{{$ $ $
 
 	
 !9r;   certreturnc           
         t          j        dt          j        t          j        |                                                                           t          j        d| j	        i          g| d         d         dd          gi          S )a  
    Format an ASN.1 ``SigningCertificate`` object, where the certificate
    is identified by its SHA-1 digest.

    :param cert:
        An X.509 certificate.
    :return:
        A :class:`tsp.SigningCertificate` object referring to the original
        certificate.
    certsdirectory_nametbs_certificateserial_numberissuerra   )	cert_hashissuer_serial)
r   SigningCertificate	ESSCertIDhashlibsha1dumpdigestr   GeneralNamerc   )r[   s    r:   r$   r$      s     !%,\$))++%>%>%E%E%G%G !% 0%5t{$C!" !"'
 .22C-D /.	* 	*  	
  r;   sha256c                 n   t          |          }t          j        |          }|                    |                                            |                                }t          j        dt          j        d|i|t          j
        d| j        i          g| d         d         dd          gi          S )a  
    Format an ASN.1 ``SigningCertificateV2`` value, where the certificate
    is identified by the hash algorithm specified.

    :param cert:
        An X.509 certificate.
    :param hash_algo:
        Hash algorithm to use to digest the certificate.
        Default is SHA-256.
    :return:
        A :class:`tsp.SigningCertificateV2` object referring to the original
        certificate.
    r^   	algorithmr_   r`   ra   rb   )hash_algorithmrd   re   )r    r   Hashupdaterj   finalizer   SigningCertificateV2ESSCertIDv2r   rl   rc   )r[   	hash_algo	hash_specmddigest_values        r:   r%   r%      s    $ +955I	Y		BIIdiikk;;==L#+6	*B%1 !% 0%5t{$C!" !"'
 .22C-D /.	* 	*  	
  r;   certidc                 ~   t          |t          j                  rd}n|d         d         j        }t	          |          }t          j        |          }|                    |                                            |	                                }|d         j        }||k    rdS |d         }| pt          ||           S )a  
    Match an ``ESSCertID`` value against a certificate.

    :param cert:
        The certificate to match against.
    :param certid:
        The ``ESSCertID`` value.
    :return:
        ``True`` if the ``ESSCertID`` matches the certificate,
        ``False`` otherwise.
    ri   rp   ro   rd   Fre   )
isinstancer   rg   rS   r    r   rq   rr   rj   rs   r&   )r[   rz   rv   rw   rx   ry   expected_digest_valueexpected_issuer_serials           r:   r'   r'      s     &#-(( A		+,[9@	*955I	Y		BIIdiikk;;==L";/6,,,u/5o/F%% )<* * r;   r~   c                    |d         d         }| d         }t          |t          j                  r3t          |          dk    s|d         j        dk    rdS |d         j        }	 |                                |j                                        k    p
||j        k    }n# t          $ r d}Y nw xY w|o| d         |k    S )a~  
    Match the issuer and serial number of an X.509 certificate against some
    expected identifier.

    :param expected_issuer_serial:
        A certificate identifier, either :class:`cms.IssuerAndSerialNumber`
        or :class:`tsp.IssuerSerial`.
    :param cert:
        An :class:`x509.Certificate`.
    :return:
        ``True`` if there's a match, ``False`` otherwise.
    r`   ra   rc   rY   r   r_   F)	r|   r   GeneralNamesrZ   rU   chosenrj   rc   
ValueError)r~   r[   serial_asn1expected_issuerissuer_matchs        r:   r&   r&     s    & ()/:K,X6O /4#455 4  A%%q!&*:::5)!,3  ""dk&6&6&8&88 .$+- 	     	O/@KOs   %:B   B/.B/c                   (     e Zd ZdZdef fdZ xZS )r   z1
    Error encountered while signing a file.
    msgc                 J    || _          t                      j        |g|R   d S r3   )r   r6   r7   )r8   r   argsr9   s      r:   r7   zSigningError.__init__Q  s/    $t$$$$$$r;   )r<   r=   r>   r?   r4   r7   r@   rA   s   @r:   r   r   L  sN         %C % % % % % % % % % %r;   r   c                       e Zd ZdZdS )r   z=
    Error raised when a signer was judged unacceptable.
    NrC   rD   r;   r:   r   r   V  s          	Dr;   r   c                     |                                  dk    rt          j        d          S  t          t          |                                                       S )Nshake256@   )digest_size)lowerr   SHAKE256getattrupperro   s    r:   r    r    ^  sL    J&&2....1wvy0011333r;   Fc                 F    t          |           }|rt          |          n|S r3   )r    r   )ro   	prehashedrv   s      r:   r!   r!   f  s)     +955I#,;9Y);r;   mechc                 >    | j         }|dk    rdS |dk    rdS | j        S )a%  
    Internal function that takes a :class:`.SignedDigestAlgorithm` instance
    and returns the name of the digest algorithm that has to be used to compute
    the ``messageDigest`` attribute.

    :param mech:
        A signature mechanism.
    :return:
        A digest algorithm name.
    ed25519sha512ed448r   )signature_algorv   )r   sig_algos     r:   r   r   m  s4     "H9x	W		z~r;   paramsc                 $   | d         }|d         j         }|                                |                                k    rt          d| d| d          | d         }|d         j         dk    st          d          |d	         d         j         }||k    r!t                              d
| d| d           | d         j         }t          |          }t          ||          }	t          j	        t          j
        |          |          }
|
|	fS )zs
    Extract PSS padding settings and message digest from an
    ``RSASSAPSSParams`` value.

    Internal API.
    rp   ro   zPSS MD 'z ' must agree with signature MD 'z'.mask_gen_algorithmmgf1zOnly MFG1 is supported
parameterszMessage digest for MGF1 is z", and the one used for signing is zL. If these do not agree, some software may refuse to validate the signature.salt_length)r   r   )mgfr   )rS   casefoldr   NotImplementedErrorloggerwarningr    r!   r   PSSMGF1)r   digest_algorithmr   rv   md_namemgamgf_md_namesalt_lenmgf_mdrx   pss_paddings              r:   r#   r#     s\    (..>'?I$+G-668888(w ( (#( ( (
 
 	
 #))=">C{"f,,!":;;;l#K07Kg1+ 1 1!1 1 1	
 	
 	

 =)0H'44F	/9	M	M	MB+L6***  K ?r;   r   c           
         |                                 }t          j        | j                                                  }t          |t                    st          dt          |                     t          |          }t          j        ||          }t          j        t          j        d|i          t          j        dt          j        d|i          d          |d          S )a"  
    Figure out the optimal RSASSA-PSS parameters for a given certificate.
    The subject's public key must be an RSA key.

    :param cert:
        An RSA X.509 certificate.
    :param digest_algorithm:
        The digest algorithm to use.
    :return:
        RSASSA-PSS parameters.
    z&Expected RSA key, but got key of type ro   r   )ro   r   )rp   r   r   )r   r   load_der_public_key
public_keyrj   r|   r   r   rI   r    r   calculate_max_pss_salt_lengthr	   RSASSAPSSParamsDigestAlgorithmMaskGenAlgorithm)r[   r   keyrx   optimal_salt_lens        r:   r"   r"     s     (--//

+DO,@,@,B,B
C
CCc<(( QODIIOOPPP	#$4	5	5B <S"EE #3./  #("8!'"'"7$&67# # # # ,	
 	
  r;   T)frozenc                   l    e Zd ZU dZej        ed<   	 eej                 ed<   	 eej	                 ed<   dS )r   zT
    Value type to describe certificates included in a CMS signed data payload.
    signer_certother_certsattribute_certsN)
r<   r=   r>   r?   r   Certificate__annotations__r   r
   AttributeCertificateV2rD   r;   r:   r   r     sg           !!!! d&'''' #45555 r;   r   sidc                       j         dk    r fdS  j         dk    r+ j        j        t                              d           fdS t
          )Nissuer_and_serial_numberc                 .    t          j        |           S r3   )r&   r   )cr   s    r:   <lambda>z'_get_signer_predicate.<locals>.<lambda>  s    ,SZ;; r;   subject_key_identifierzThe signature in this SignedData value seems to be identified by a subject key identifier --- this is legal in CMS, but many PDF viewers and SDKs do not support this feature.c                     | j         k    S r3   )key_identifier)r   skis    r:   r   z'_get_signer_predicate.<locals>.<lambda>  s    )S0 r;   )rU   r   rS   r   r   r   )r   r   s   `@r:   _get_signer_predicater     sm    
x---;;;;;	-	-	- j<	
 	
 	

 10000
r;   c                     t          |d                   }d }g }| D ]%} ||          r|}|                    |           &|t          d          ||fS )Nr   z,signer certificate not included in signature)r   appendr(   )r^   signer_info	predicater[   r   r   s         r:   _partition_certsr     s|    
 &k%&899IDK " "9Q<< 	"DDq!!!!| !OPPPr;   signed_datac                 V    	 | d         \  }|S # t           $ r t          d          w xY w)a5  
    Extract the unique ``SignerInfo`` entry of a CMS signed data value, or
    throw a ``ValueError``.

    :param signed_data:
        A CMS ``SignedData`` value.
    :return:
        A CMS ``SignerInfo`` value.
    :raises ValueError:
        If the number of ``SignerInfo`` values is not exactly one.
    signer_infosz-signer_infos should contain exactly one entry)r   r(   )r   r   s     r:   r   r     sI    
$^4 
 
 
 ;
 
 	

s    (c                 @   g }g }| d         D ]\}|j                                         }|j        dk    r|                    |           <|j        dk    r|                    |           ]t	          |           }t          ||          \  }}t          |||          }|S )a  
    Extract and classify embedded certificates found in the ``certificates``
    field of the signed data value.

    :param signed_data:
        A CMS ``SignedData`` value.
    :return:
        A :class:`SignedDataCerts` object containing the embedded certificates.
    certificatescertificatev2_attr_cert)r   r   r   )r   untagrU   r   r   r   r   )	r   r^   
attr_certsr   r[   r   r   r   	cert_infos	            r:   r   r   "  s     EJ( $ $x~~6]""LLV~%%d###%k22K/{CCK"  I
 r;   stream
byte_rangemd_algorithmc                 .   t          |          }t          j        |          }d}t          |          }t	          j        |          D ]7\  }}	|                     |           t	          j        || ||	           ||	z  }8||                                fS )a  
    Internal API to compute byte range digests. Potentially dangerous if used
    without due caution.

    :param stream:
        Stream over which to compute the digest. Must support seeking and
        reading.
    :param byte_range:
        The byte range, as a list of (offset, length) pairs, flattened.
    :param md_algorithm:
        The message digest algorithm to use.
    :param chunk_size:
        The I/O chunk size to use.
    :return:
        A tuple of the total digested length, and the actual digest.
    r   )max_read)	r    r   rq   	bytearrayr   	pair_iterseekchunked_digestrs   )
r   r   r   
chunk_sizemd_specrx   	total_len	chunk_buflo	chunk_lens
             r:   r)   r)   ?  s    , )66G	W		B
 I*%%I
33  IBIvrIFFFFY		bkkmm##r;   )rm   )F)Nr?   rh   loggingdataclassesr   typingr   r   r   r   r   
asn1cryptor	   r
   r   r   asn1crypto.algosr   cryptography.hazmat.primitivesr   r   )cryptography.hazmat.primitives.asymmetricr   -cryptography.hazmat.primitives.asymmetric.rsar   /cryptography.hazmat.primitives.asymmetric.utilsr   pyhanko.keyspyhanko.pdf_utilsr   __all__	getLoggerr<   r   r   r*   r+   r(   r   KeyErrorr   r   r   r   r   rf   r$   rt   r%   rg   ru   r'   IssuerAndSerialNumberIssuerSerialboolr&   r   r   HashAlgorithmr    r!   r4   r   r   r#   r"   r   SignerIdentifierr   r   
SignedData
SignerInfor   r   DEFAULT_CHUNK_SIZEintbytesr)   rD   r;   r:   <module>r     sD      ! ! ! ! ! ! 3 3 3 3 3 3 3 3 3 3 3 3 3 3 , , , , , , , , , , , , 2 2 2 2 2 2 @ @ @ @ @ @ @ @ = = = = = = F F F F F F E E E E E E     " " " " " "  @ 
	8	$	$	* 	* 	* 	* 	*J 	* 	* 	*, , , , ,. , , ,	 	 	 	 	. 	 	 	  "	 	 	 	 	 	 	 		 	 	 	 	
 	 	 	#O #O #OL  2 !1  c6L        H '/+ +

++ + + +\

$)#-*H$I   @1!#";S=M"MN1

1 
1 1 1 1h% % % % %: % % %	 	 	 	 	l 	 	 	4U63G-H 4 4 4 4 < <
6*+< < < <*? C    0 @E$ $!$ $ $ $N'

'.1'
' ' ' 'T $       *s3       $
S^ 
 
 
 
 
*#. _    B &	#$ #$#$#$ #$
 3:#$ #$ #$ #$ #$ #$r;   