o
    vh                     @   s  d dl Z d dlZd dlZd dlZd dlZd dl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 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mZmZ d d	l 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-m.Z. d dl/m0Z0m1Z1 d dl2m3Z3m4Z4 d dl5m6Z6m7Z7 d dl8m9Z9 d dl:m;Z; d dl<m=Z= ddl>m?Z?m@Z@ ddlAmBZBmCZCmDZDmEZEmFZF ddlGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZP ddlQmRZRmSZS ddlTmUZUmVZVmWZW ddlXmYZY eZe[Z\eddG dd dZ]G dd  d eJe j^Z_G d!d" d"e_eUZ`G d#d$ d$e_eVZaG d%d& d&e_eWZb	 e?cd'Zd	 e?cd(Ze	 	 dtd)d*Zfdtd+d,Zgdtd-d.ZhejiG d/d0 d0ejjZk	dud1eld2eYfd3d4Zmd5ed6ejnd7elfd8d9Zod5ed6ejnd7elfd:d;Zpd6ejnd<ejd=elfd>d?Zqd5ed@ee!jreef fdAdBZsd5ed6ejtd7elfdCdDZud6ejtdEed<ejdFeld=elf
dGdHZvd7eldIejwdJe]fdKdLZx	dudMeejw d1eld2eYdJe]d@ejyf
dNdOZzG dPdQ dQe{Z|G dRdS dSZ}G dTdU dUej~ZG dVdW dWej~ZedXZdYe!jrdZejd[eel d@e9fd\d]ZG d^d_ d_e}eRZeRe d`ejdae}d@eel fdbdcZddejydae}d@eeel eeY f fdedfZdge?jfdhdiZdjdk Zdldm Zdndo Zdpdq ZeNjG drds dseNZdS )v    N)	dataclass)sha1sha256)DictListOptionalSetTupleUnion)algoscmscorex509)RSAESOAEPParams)KeyEncryptionAlgorithmKeyEncryptionAlgorithmId)PrivateKeyInfoPublicKeyAlgorithmPublicKeyInfo)hasheskeywrapserialization)ECDHEllipticCurvePrivateKeyEllipticCurvePublicKey)generate_private_key)MGF1OAEPAsymmetricPaddingPKCS1v15)RSAPrivateKeyRSAPublicKey)X448PrivateKeyX448PublicKey)X25519PrivateKeyX25519PublicKey)KeyDerivationFunction)X963KDF)pkcs12   )genericmisc   )aes_cbc_decryptaes_cbc_encryptrc2_decryptrc4_encrypttripledes_decrypt)	
AuthResult
AuthStatusCryptFilterCryptFilterBuilderCryptFilterConfigurationIdentityCryptFilterSecurityHandlerSecurityHandlerVersionbuild_crypt_filter)SerialisableCredentialSerialisedCredential)AESCryptFilterMixinAESGCMCryptFilterMixinRC4CryptFilterMixin)PubKeyPermissionsT)frozenc                   @   s(   e Zd ZU dZeed< 	 dZeed< dS )RecipientEncryptionPolicyFignore_key_usageprefer_oaepN)__name__
__module____qualname__rC   bool__annotations__rD    rJ   rJ   \/var/www/html/hyperkenya/venv/lib/python3.10/site-packages/pyhanko/pdf_utils/crypt/pubkey.pyrB   L   s
   
 rB   c                       s   e Zd ZU dZdZed ed< dddd fdd	
Zed
e	fddZ
 fddZe fdeej dedefddZd
efddZd
efddZ fddZ  ZS )PubKeyCryptFiltera  
    Crypt filter for use with public key security handler.
    These are a little more independent than their counterparts for
    the standard security handlers, since different crypt filters
    can cater to different sets of recipients.

    :param recipients:
        List of CMS objects encoding recipient information for this crypt
        filters.
    :param acts_as_default:
        Indicates whether this filter is intended to be used in
        ``/StrF`` or ``/StmF``.
    :param encrypt_metadata:
        Whether this crypt filter should encrypt document-level metadata.

        .. warning::
            See :class:`.SecurityHandler` for some background on the
            way pyHanko interprets this value.
    NPubKeySecurityHandler_handlerFT)
recipientsacts_as_defaultencrypt_metadatac                   s:   || _ || _|| _d| _d  | _| _t jdi | d S )NFrJ   )rO   rP   rQ   _pubkey_auth_failed_shared_key_recp_key_seedsuper__init__)selfrO   rP   rQ   kwargs	__class__rJ   rK   rV   s   s   zPubKeyCryptFilter.__init__returnc                 C      | j S N)rR   rW   rJ   rJ   rK   _auth_failed      zPubKeyCryptFilter._auth_failedc                    s*   t |tstt | d  | _| _d S r]   )
isinstancerM   	TypeErrorrU   _set_security_handlerrS   rT   )rW   handlerrY   rJ   rK   rc      s   
z'PubKeyCryptFilter._set_security_handlercertspolicypermsc                 C   sv   | j s| jrtd| jdu rtd| _g | _| jdus#| jdu r(tdt|| j||| j d}| j	| dS )ay  
        Add recipients to this crypt filter.
        This always adds one full CMS object to the Recipients array

        :param certs:
            A list of recipient certificates.
        :param policy:
            Encryption policy choices for the chosen set of recipients.
        :param perms:
            The permission bits to assign to the listed recipients.
        zCA non-default crypt filter cannot have multiple sets of recipients.N   zYAdding recipients after deriving the shared key or before authenticating is not possible.)rf   include_permissions)
rP   rO   r+   PdfErrorsecretstoken_bytesrT   rS   construct_recipient_cmsappend)rW   re   rf   rg   new_cmsrJ   rJ   rK   add_recipients   s&   
z PubKeyCryptFilter.add_recipientsc                 C   sB   | j D ]}t||\}}|dur|| _ttj|  S qttjS )a  
        Authenticate to this crypt filter in particular.
        If used in ``/StmF`` or ``/StrF``, you don't need to worry about
        calling this method directly.

        :param credential:
            The :class:`.EnvelopeKeyDecrypter` to authenticate with.
        :return:
            An :class:`AuthResult` object indicating the level of access
            obtained.
        N)rO   read_seed_from_recipient_cmsrT   r2   r3   USERFAILED)rW   
credentialrecpseedrg   rJ   rJ   rK   authenticate   s   

zPubKeyCryptFilter.authenticatec                 C   s   | j d usJ | jd u rtd| j jtjkrt }nt }|	| j | j
D ]	}|	|  q(| js=| jr=|	d | d | j S )Nz&No seed available; authenticate first.s   )rN   rT   r+   rj   versionr9   AES256r   r   updaterO   dumprQ   rP   digestkeylen)rW   mdru   rJ   rJ   rK   derive_shared_encryption_key   s   



z.PubKeyCryptFilter.derive_shared_encryption_keyc                    sd   t   }t| jd |d< tdd | jD }| jr"||d< n|d |d< t| j	|d< |S )N   /Lengthc                 s       | ]
}t | V  qd S r]   r*   ByteStringObjectr{   .0ru   rJ   rJ   rK   	<genexpr>   s    
z2PubKeyCryptFilter.as_pdf_object.<locals>.<genexpr>/Recipientsr   /EncryptMetadata)
rU   as_pdf_objectr*   NumberObjectr}   ArrayObjectrO   rP   BooleanObjectrQ   )rW   resultrO   rY   rJ   rK   r      s   


zPubKeyCryptFilter.as_pdf_object)rE   rF   rG   __doc__rN   r   rI   rV   propertyrH   r_   rc   r@   allow_everythingr   r   CertificaterB   rp   r2   rw   bytesr   r   __classcell__rJ   rJ   rY   rK   rL   \   s*   
 

+rL   c                   @      e Zd ZdZdS )PubKeyAESCryptFilterz<
    AES crypt filter for public key security handlers.
    NrE   rF   rG   r   rJ   rJ   rJ   rK   r          r   c                   @   r   )PubKeyAESGCMCryptFilterz@
    AES-GCM crypt filter for public key security handlers.
    Nr   rJ   rJ   rJ   rK   r      r   r   c                   @   r   )PubKeyRC4CryptFilterz<
    RC4 crypt filter for public key security handlers.
    Nr   rJ   rJ   rJ   rK   r      r   r   z/DefaultCryptFilterz/DefEmbeddedFilec                 C      t tt| d||dittdS NT)r}   rP   rO   rQ   default_stream_filterdefault_string_filter)r6   DEFAULT_CRYPT_FILTERr   r}   rO   rQ   rJ   rJ   rK   _pubkey_rc4_config     r   c                 C   r   r   )r6   r   r   r   rJ   rJ   rK   _pubkey_aes_config'  r   r   c                 C   s   t ttd| |dittdS )NT)rP   rO   rQ   r   )r6   r   r   rO   rQ   rJ   rJ   rK   _pubkey_gcm_config6  s   r   c                   @   s.   e Zd ZdZedZedZedZdS )PubKeyAdbeSubFilterz{
    Enum describing the different subfilters that can be used for public key
    encryption in the PDF specification.
    z/adbe.pkcs7.s3z/adbe.pkcs7.s4z/adbe.pkcs7.s5N)	rE   rF   rG   r   r*   
NameObjectS3S4S5rJ   rJ   rJ   rK   r   D  s
    

r   rv   rg   c                 C   s&   t | dksJ | |r|  S d S )Nrh       )lenas_bytes)rv   rg   ri   rJ   rJ   rK   construct_envelope_contentP  s   r   pub_key_inforidenvelope_keyc                 C   sR   t  }tdtdi}t|  }t|tsJ |j	||d}t
|||dS )N	algorithmrsaes_pkcs1v15paddingr   algoencrypted_data)r   r   r   r   r   load_der_public_keyr{   ra   r!   encrypt_format_ktri)r   r   r   r   r   pub_keyr   rJ   rJ   rK   _rsaes_pkcs1v15_recipientW  s   r   c                 C   s   ddl m} ddlm} || }||}ttdtd|idd|iddd}tt	||d d	}t
|  }	t|	tsBJ |	j||d
}
t|||
dS )Nr   get_pyca_cryptography_hash)select_suitable_signing_md
rsaes_oaepr   mgf1r   
parameters)hash_algorithmmask_gen_algorithmmgfr   labelr   r   )pyhanko.sign.generalr   pyhanko.sign.signers.pdf_cmsr   r   r   r   r   r   r   r   r   r{   ra   r!   r   r   )r   r   r   r   r   digest_function_namedigest_specr   r   r   r   rJ   rJ   rK   _rsaes_oaep_recipienth  s(   r   r   r   c              
   C   s   t dt d| ||diS )Nktrir   )rx   r   key_encryption_algorithmencrypted_key)r   RecipientInfoKeyTransRecipientInfor   rJ   rJ   rK   r     s   r   r[   c                 C   s~   | j }|dkr| jd }n	|dkrd}nd}|dkr%t tdtdfS |dkr4t td	td
fS t tdtdfS )Necr)   x25519      aes128_wrapz1.3.132.1.11.1   aes192_wrapz1.3.132.1.11.2aes256_wrapz1.3.132.1.11.3)r   bit_sizer   SHA256r   SHA384SHA512)r   	algo_nameapprox_sec_levelrJ   rJ   rK   _choose_ecdh_settings  s(   r   c                 C   s   t | \}}}td|i}t|  }t|tr&t|j}|	t
 |}	n t|tr5t }|	|}	nt|trDt }|	|}	ntt| tjjtjj}
td}t|||d}||	}tj||d}t||
t ||d||dS )Nr      
kdf_digestkey_wrap_algouser_keying_material)wrapping_keykey_to_wrapr   r   originator_keyr   ukmr   )!r   r   r   r   r{   ra   r   generate_ec_private_keycurveexchanger   r%   r$   generater#   r"   NotImplementedErrorr   load
public_keypublic_bytesEncodingDERPublicFormatSubjectPublicKeyInfork   rl   _kdf_for_exchangederiver   aes_key_wrap_format_karir   )r   r   r   r   key_wrap_algo_idkey_exch_algo_idr   r   r   
ecdh_valueoriginator_key_infor   kdfkekr   rJ   rJ   rK   _ecdh_recipient  sT   






r  r   r   c                 C   s8   t jdt dt jd|d||t | |dgddS )Nkari   r   )namevalue)r   r   )rx   
originatorr   r   recipient_encrypted_keys)r   r   KeyAgreeRecipientInfoOriginatorIdentifierOrKeyRecipientEncryptedKeyr   rJ   rJ   rK   r     s    r   certrf   c           
      C   s   |j }|d }|d j}t| dksJ |js.|j}|d u s#d|jvr.td|jj dt	
|j|jd}|dkrRt	d|i}|jrLt||| S t||| S |d	v rct	d|i}	t||	| S td
| d)Nr       key_enciphermentzCertificate for subject z8 does not have the 'key_encipherment' key usage bit set.)issuerserial_numberrsaissuer_and_serial_number)r   r   x448zCannot encrypt for key type '')r   nativer   rC   key_usage_valuer+   PdfWriteErrorsubjecthuman_friendlyr   IssuerAndSerialNumberr  r  RecipientIdentifierrD   r   r   KeyAgreementRecipientIdentifierr  r   )
r   r  rf   r   pubkey_algo_infoalgorithm_name	key_usageiss_serial_ridr   ka_ridrJ   rJ   rK   _recipient_info  s8   

r$  certificatesc                    s   t |||d}td t |d d\}} fdd| D }ttd|d}	tt	d|	|d	}
t
d
||
d}tt	d|dS )N)ri   r  )ivc                    s   g | ]	}t  |d qS ))rf   )r$  )r   r  r   rf   rJ   rK   
<listcomp>^  s    z+construct_recipient_cms.<locals>.<listcomp>
aes256_cbcr   data)content_typecontent_encryption_algorithmencrypted_contentr   )rx   recipient_infosencrypted_content_infoenveloped_data)r+  content)r   rk   rl   r.   r   EncryptionAlgorithmr   EncryptionAlgorithmIdEncryptedContentInfoContentTypeEnvelopedDataContentInfo)r%  rv   rg   rf   ri   envelope_contentr&  encrypted_envelope_content	rec_infosr   r/  r0  rJ   r'  rK   rm   =  s@   


	rm   c                   @   s   e Zd ZdS )InappropriateCredentialErrorN)rE   rF   rG   rJ   rJ   rJ   rK   r;    s    r;  c                
   @   s^   e Zd ZdZedejfddZdede	j
defddZdede	j
d	e	jd
edef
ddZdS )EnvelopeKeyDecrypterz
    General credential class for use with public key security handlers.

    This allows the key decryption process to happen offline, e.g. on a smart
    card.
    r[   c                 C      t )zI
        :return:
            Return the recipient's certificate
        r   r^   rJ   rJ   rK   r    s   zEnvelopeKeyDecrypter.certr   algo_paramsc                 C   r=  )a  
        Invoke the actual key decryption algorithm.
        Used with key transport.

        :param encrypted_key:
            Payload to decrypt.
        :param algo_params:
            Specification of the encryption algorithm as a CMS object.
        :raises InappropriateCredentialError:
            if the credential cannot be used for key transport.
        :return:
            The decrypted payload.
        r>  )rW   r   r?  rJ   rJ   rK   decrypt  s   zEnvelopeKeyDecrypter.decryptoriginator_identifierr   c                 C   r=  )a"  
        Decrypt an envelope key using a key derived from a key exchange.

        :param encrypted_key:
            Payload to decrypt.
        :param algo_params:
            Specification of the encryption algorithm as a CMS object.
        :param originator_identifier:
            Information about the originator necessary to complete the key
            exchange.
        :param user_keying_material:
            The user keying material that will be used in the key derivation.
        :return:
            The decrypted payload.
        r>  )rW   r   r?  rA  r   rJ   rJ   rK   decrypt_with_exchange  s   z*EnvelopeKeyDecrypter.decrypt_with_exchangeN)rE   rF   rG   r   r   r   r   r  r   r   r   r@  r  rB  rJ   rJ   rJ   rK   r<    s,    
r<  c                   @   s   e Zd ZdefdejfgZdS )_PrivKeyAndCertkeyr  N)rE   rF   rG   r   r   r   _fieldsrJ   rJ   rJ   rK   rC    s    rC  c                   @   s4   e Zd ZdefdejdddfdejddifgZd	S )
ECCCMSSharedInfokey_infoentityUInfor   T)explicitoptionalsuppPubInforI  r)   N)rE   rF   rG   r   r   OctetStringrE  rJ   rJ   rJ   rK   rF    s    rF  zaes(\d+)_wrap(_pad)?r   r   r   c              
   C   s^   |d j }t|}|st| dt|d}t| |d t||t	d|d
 dS )Nr   * is not a supported key wrapping algorithmr,   r   z>I)rG  rH  rK  )r   length
sharedinfo)r  AES_WRAP_PATTERN	fullmatchr   intgroupr'   rF  structpackr{   )r   r   r   r   
wrap_matchkek_bit_lenrJ   rJ   rK   r     s$   


r   c                
   @   s   e Zd ZdZedZedefddZ	de
fddZede
fd	d
ZdejdefddZedejfddZedddZedddZde
dejde
fddZde
dejdejdee
 de
f
ddZdS )SimpleEnvelopeKeyDecrypterz
    Implementation of :class:`.EnvelopeKeyDecrypter` where the private key
    is an RSA or ECC key residing in memory.

    :param cert:
        The recipient's certificate.
    :param private_key:
        The recipient's private key.
    z1\.3\.132\.1\.11\.(\d+)r[   c                 C   s   dS )Nraw_privkeyrJ   clsrJ   rJ   rK   get_name  s   z#SimpleEnvelopeKeyDecrypter.get_namec                 C   s   | j | jd}t| S )N)rD  r  )private_keyr  rC  r{   )rW   valuesrJ   rJ   rK   
_ser_value  s   z%SimpleEnvelopeKeyDecrypter._ser_valuer*  c              
   C   sP   zt |}|d }|d }W n ty! } ztd|d }~ww t||dS )NrD  r  z-Failed to decode serialised pubkey credentialr  r]  )rC  r   
ValueErrorr+   PdfReadErrorrX  )r[  r*  decodedrD  r  erJ   rJ   rK   _deser_value  s   
z'SimpleEnvelopeKeyDecrypter._deser_valuer  r]  c                 C   s   || _ || _d S r]   )r]  _cert)rW   r  r]  rJ   rJ   rK   rV     s   
z#SimpleEnvelopeKeyDecrypter.__init__c                 C   r\   r]   )rf  r^   rJ   rJ   rK   r    r`   zSimpleEnvelopeKeyDecrypter.certNc              
   C   sx   ddl m} z|| |d}ddl m} ||}W n tttfy5 } ztjd|d W Y d}~dS d}~ww t||dS )	a  
        Load a key decrypter using key material from files on disk.

        :param key_file:
            File containing the recipient's private key.
        :param cert_file:
            File containing the recipient's certificate.
        :param key_passphrase:
            Passphrase for the key file, if applicable.
        :return:
            An instance of :class:`.SimpleEnvelopeKeyDecrypter`.
        r  )load_private_key_from_pemder)
passphrase)load_cert_from_pemderz%Could not load cryptographic materialexc_infoNr`  )	keysrg  ri  IOErrorra  rb   loggererrorrX  )key_file	cert_filekey_passphraserg  r]  ri  r  rd  rJ   rJ   rK   r     s   zSimpleEnvelopeKeyDecrypter.loadc              
   C   s   z4t |d}| }W d   n1 sw   Y  t||\}}}ddlm}m}	 ||}|	|}W n! ttt	fyU }
 zt
jd| d|
d W Y d}
~
dS d}
~
ww t||dS )	aZ  
        Load a key decrypter using key material from a PKCS#12 file on disk.

        :param pfx_file:
            Path to the PKCS#12 file containing the key material.
        :param passphrase:
            Passphrase for the private key, if applicable.
        :return:
            An instance of :class:`.SimpleEnvelopeKeyDecrypter`.
        rbNr  )(translate_pyca_cryptography_cert_to_asn1'translate_pyca_cryptography_key_to_asn1zCould not open PKCS#12 file .rj  r`  )openreadr(   load_key_and_certificateskeys.internalrt  ru  rm  ra  rb   rn  ro  rX  )r[  pfx_filerh  f	pfx_bytesr]  r  other_certsrt  ru  rd  rJ   rJ   rK   load_pkcs126  s    

z&SimpleEnvelopeKeyDecrypter.load_pkcs12r   r?  c           
      C   s   |d j }|dkrt }nD|dkrIddlm} |d }|d }|d j }|dkr0td	| d
tt||d d j d||d d j dd}ntd| dtj| j	
 dd}	t|	tsdtd|	j||dS )a  
        Decrypt the payload using RSA with PKCS#1 v1.5 padding or OAEP.
        Other schemes are not (currently) supported by this implementation.

        :param encrypted_key:
            Payload to decrypt.
        :param algo_params:
            Specification of the encryption algorithm as a CMS object.
            Must use ``rsaes_pkcs1v15`` or ``rsaes_oaep``.
        :return:
            The decrypted payload.
        r   r   r   r   r   r   r   r   z#Only MGF1 is implemented, but got 'r  )r   r   Nr   zSOnly 'rsaes_pkcs1v15' and 'rsaes_oaep' are supported for envelope decryption, not 'z'.passwordz5The loaded key does not seem to be an RSA private keyr   )r  r   r   r   r   r   r   r   load_der_private_keyr]  r{   ra   r    r;  r@  )
rW   r   r?  r   r   r   oaep_paramsr   mgf_namepriv_keyrJ   rJ   rK   r@  W  sH   




z"SimpleEnvelopeKeyDecrypter.decryptrA  r   c                 C   s  |d }| j |j}d}|r%t t t t d|	dd}|s+t
dtj|d  }|d j}	t|	sFt
|	 d|	drNtjntj}
t|||d	}|jd
krat
d|j }t| }tj| j dd}d}t|trt|tr|j j|j jkrt!||"t# |}n,t|t$rt|t%st!||"|}nt|t&rt|t'st!||"|}nt(d|)|}|
||dS )am  
        Decrypt the payload using a key agreed via ephemeral-static
        standard (non-cofactor) ECDH with X9.63 key derivation.
        Other schemes aer not supported at this time.


        :param encrypted_key:
            Payload to decrypt.
        :param algo_params:
            Specification of the encryption algorithm as a CMS object.
        :param originator_identifier:
            The originator info, which must be an EC key.
        :param user_keying_material:
            The user keying material that will be used in the key derivation.
        :return:
            The decrypted payload.
        r   N)0123r,   zGOnly dhSinglePass-stdDH algorithms from SEC 1 / RFC 5753 are supported.r   rM  _padr   r   z Only originator_key is supportedr  zCOriginator's public key is not compatible with selected private keyz4The loaded key does not seem to be an EC private key)r   wrapped_key)*dhsinglepass_stddh_arc_patternrQ  dottedr   SHA224r   r   r   getrS  r   r   r   r   r{   r  rP  endswithr   aes_key_unwrap_with_paddingaes_key_unwrapr   r  chosenuntagr   r   r  r]  ra   r   r   r   ra  r   r   r$   r%   r"   r#   r;  r   )rW   r   r?  rA  r   oidmatchr   r   r   
unwrap_keyr  originator_pub_key_infooriginator_pub_keyr  mismatch_msgr   derived_kekrJ   rJ   rK   rB    s~   










z0SimpleEnvelopeKeyDecrypter.decrypt_with_exchanger]   )rE   rF   rG   r   recompiler  classmethodstrr\  r   r_  re  r   r   r   rV   r   r  staticmethodr   r  r   r   r@  r  r   rB  rJ   rJ   rJ   rK   rX    sB    

 
6rX  ed	decrypterc           
      C   s  | d D ]}|j dkra|j}|d j}t|tjstd|d }|d j}|jj|kr`|jj	|kr`z|
|d j|d W   S  tyN } z|d }~w ty_ } ztd	|d }~ww q|j d
kr|j}|d D ]^}	|	d j}t|tjs~td|d }|d j}|jj|kr|jj	|krz|j|	d j|d |d |d jdW     S  ty } z|d }~w ty } ztd	|d }~ww qmqtdd S )Nr.  r   r   z;Recipient identifier must be of type IssuerAndSerialNumber.r  r  r   r   zFailed to decrypt envelope keyr  r
  r	  r   )rA  r   zLRecipientInfo must be of type KeyTransRecipientInfo or KeyAgreeRecipientInfo)r  r  ra   r   r  r   r  r  r  r  r@  r;  	Exceptionr+   rb  rB  )
r  r  rec_infor   issuer_and_serialr  serialrd  r  recipient_enc_keyrJ   rJ   rK   read_envelope_key  s   






r  recipient_cmsc              	   C   sD  | d j }|dkrtd| | d }|d }t||}|d u r#dS |d }|d j }z|j}W n ttfyA   |d	 j }Y nw |d
krJtd|dkrX|j}	t	|||	}
n/|dkrf|j}	t
|||	}
n!|dkrt|j}	t|||	}
n|dkr~t||}
n	td| d|
d d }d }t|
dkrt|
dd  }||fS )Nr+  r0  z7Recipient CMS content type must be enveloped data, not r1  r/  )NNr,  r-  r   desz2Support for DES has been dropped in pyHanko 0.26.0aes	tripledesrc2rc4zCipher z is not allowed in PDF 2.0.rh      )r  r+   rb  r  encryption_cipherra  KeyErrorr   encryption_ivr-   r1   r/   r0   r   r@   
from_bytes)r  r  r+  r  r/  r   r   r9  cipher_namer&  r1  rv   rg   rJ   rJ   rK   rq   ;  sd   



rq   cfdictc                 C   s\   z| d }W n t y   tdw t|tjr|f}dd |D }| dd}||dS )Nr   z.PubKey CF dictionary must have /Recipients keyc                 S      g | ]	}t j|jqS rJ   r   r7  r   original_bytesr   xrJ   rJ   rK   r(    s    z0_read_generic_pubkey_cf_info.<locals>.<listcomp>r   Tr   )r  r+   rb  ra   r*   r   r  )r  rO   recipient_objsrQ   rJ   rJ   rK   _read_generic_pubkey_cf_infoz  s   
r  c                 C   s(   |  dd}td|d |dt| S )Nr   (   r   r}   rP   rJ   )r  r   r  )r  rP   keylen_bitsrJ   rJ   rK   _build_legacy_pubkey_cf  s   r  c                 C      t dd|dt| S )Nr   r  rJ   r   r  r  rP   rJ   rJ   rK   _build_aes128_pubkey_cf     r  c                 C   r  )Nr  r  rJ   r  r  rJ   rJ   rK   _build_aes256_pubkey_cf  r  r  c                 C   s   t dd|it| S )NrP   rJ   )r   r  r  rJ   rJ   rK   _build_aesgcm_pubkey_cf  s
   r  c                       s  e Zd ZU dZedeedeedeede	eddd iZ
eejef ed	< ed
ejdde de dfdeej dedededd f
ddZ					d6dededed dee dee f
 fddZedefddZede e fddZ!ed ej"d!ede#fd"d#Z$ed$ej"ded f fd%d&Z%ed$ej"fd'd(Z&ed$ej"fd)d*Z'ed$ej"fd+d,Z(d-d. Z)e e fdeej dedefd/d0Z*	d7d1e+e,e-f de.fd2d3Z/defd4d5Z0  Z1S )8rM   z
    Security handler for public key encryption in PDF.

    As with the standard security handler, you essentially shouldn't ever
    have to instantiate these yourself (see :meth:`build_from_certs`).
    z/V2z/AESV2z/AESV3z/AESV4z	/Identityc                 C   s   t  S r]   )r7   )___rJ   rJ   rK   <lambda>  s    zPubKeySecurityHandler.<lambda>_known_crypt_filtersr   Tre   rg   rf   pdf_macr[   c
                 K   s   |rt jnt j}d}|tjkr |rtd|dd}nt|d|d}|	r3|tjkr3|tj	 M }t
d}nd}| |||f||d|d|
}|j|||d |S )aO  
        Create a new public key security handler.

        This method takes many parameters, but only ``certs`` is mandatory.
        The default behaviour is to create a public key encryption handler
        where the underlying symmetric encryption is provided by AES-256.
        Any remaining keyword arguments will be passed to the constructor.

        :param certs:
            The recipients' certificates.
        :param keylen_bytes:
            The key length (in bytes). This is only relevant for legacy
            security handlers.
        :param version:
            The security handler version to use.
        :param use_aes:
            Use AES-128 instead of RC4 (only meaningful if the ``version``
            parameter is :attr:`~.SecurityHandlerVersion.RC4_OR_AES128`).
        :param use_crypt_filters:
            Whether to use crypt filters. This is mandatory for security
            handlers of version :attr:`~.SecurityHandlerVersion.RC4_OR_AES128`
            or higher.
        :param perms:
            Permission flags.
        :param encrypt_metadata:
            Whether to encrypt document metadata.

            .. warning::
                See :class:`.SecurityHandler` for some background on the
                way pyHanko interprets this value.
        :param pdf_mac:
            Include an ISO 32004 MAC.

            .. warning::
                Only works for PDF 2.0 security handlers.
        :param policy:
            Encryption policy choices for the chosen set of recipients.
        :return:
            An instance of :class:`.PubKeySecurityHandler`.
        Nr   )rQ   rO   r   r  )rQ   crypt_filter_configr  kdf_saltrg   rf   )r   r   r   r9   RC4_OR_AES128r   r   ry   r@   TOLERATE_MISSING_PDF_MACrk   rl   rp   )r[  re   keylen_bytesrx   use_aesuse_crypt_filtersrg   rQ   rf   r  rX   	subfiltercfcr  shrJ   rJ   rK   build_from_certs  sB   8

z&PubKeySecurityHandler.build_from_certsNrx   pubkey_handler_subfilterr  r6   r  r  c	           	         s   |t jkr|tjkrtd|d u rK|t jkr td||d}n+|t jkr-t|||d}n|t j	kr9t
||d}n|t jkrFtd||d}ntdt j||||||d || _|| _d | _d S )NzESubfilter /adbe.pkcs7.s5 is required for security handlers beyond V4.   )r}   rQ   rO   r   r  z1Failed to impute a reasonable crypt filter config)rQ   compat_entriesr  )r9   r  r   r   r+   rj   RC4_40r   RC4_LONGER_KEYSAES_GCMr   ry   r   rU   rV   r  rQ   rS   )	rW   rx   r  legacy_keylenrQ   r  r  r  r  rY   rJ   rK   rV     sT   






zPubKeySecurityHandler.__init__c                 C   s
   t dS )Nz/Adobe.PubSec)r*   r   rZ  rJ   rJ   rK   r\  Y  s   
zPubKeySecurityHandler.get_namec                 C   s   dd t D S )Nc                 S   s   h | ]}|j qS rJ   )r  r  rJ   rJ   rK   	<setcomp>_  s    zCPubKeySecurityHandler.support_generic_subfilters.<locals>.<setcomp>)r   rZ  rJ   rJ   rK   support_generic_subfilters]  s   z0PubKeySecurityHandler.support_generic_subfiltersr  rP   c                 C   s$   t | j||}|d u rtd|S )NzJAn absent CFM or CFM of /None doesn't make sense in a PubSec CF dictionary)r:   r  r+   rb  )r[  r  rP   cfrJ   rJ   rK   read_cf_dictionarya  s   z(PubKeySecurityHandler.read_cf_dictionaryencrypt_dictc                    sR   t  |}| |}|d ur|tjkrtd|d u r'|tjkr'td|S )Nz=Crypt filters require /adbe.pkcs7.s5 as the declared handler.z./adbe.pkcs7.s5 handler requires crypt filters.)rU   process_crypt_filters_determine_subfilterr   r   r+   rb  )r[  r  r  r  rY   rJ   rK   r  o  s   
z+PubKeySecurityHandler.process_crypt_filtersc              	   C   sh   | dd}|d dkrtd|d }t|ddd }|jd	td
d}t||||ddd dS )Nr   r   r   r   z"Key length must be a multiple of 8r   c                 S   s   dd | D S )Nc                 S   r  rJ   r  r  rJ   rJ   rK   r(    s    zSPubKeySecurityHandler.gather_pub_key_metadata.<locals>.<lambda>.<locals>.<listcomp>rJ   )lstrJ   rJ   rK   r    s    z?PubKeySecurityHandler.gather_pub_key_metadata.<locals>.<lambda>r   Tdefault/KDFSaltc                 S   s   t | tjtjfr| jS d S r]   )ra   r*   TextStringObjectr   r  )r  rJ   rJ   rK   r    s
   )r  r  rQ   r  )r  r+   rj   get_and_applyrH   dict)r[  r  r  r}   rO   rQ   rJ   rJ   rK   gather_pub_key_metadata  s*   
z-PubKeySecurityHandler.gather_pub_key_metadatac                 C   sL   zt j|dtd|v rtjdW S tjdW S  ty%   t d|d  w )N
/SubFilterz/CFr  z8Invalid /SubFilter in public key encryption dictionary: )r+   r  r   r   r   ra  rb  )r[  r  rJ   rJ   rK   r    s"   
z*PubKeySecurityHandler._determine_subfilterc                 C   s6   t |d }td|| || |d| |S )N/V)rx   r  r  rJ   )r9   from_numberrM   r  r  r  )r[  r  vrJ   rJ   rK   instantiate_from_pdf_object  s   z1PubKeySecurityHandler.instantiate_from_pdf_objectc                 C   s   t  }t |  |d< | jj|d< | j |d< | jr%t 	| j|d< | j
s.| jtjkr8t | jd |d< | jtjkrFt | j|d< | jtjkrV|| j  |S |  }t|tsatt dd	 |jD |d
< |S )Nz/Filterr  r  r  r   r   r   c                 s   r   r]   r   r   rJ   rJ   rK   r     s
    
z6PubKeySecurityHandler.as_pdf_object.<locals>.<genexpr>r   )r*   DictionaryObjectr   r\  r  r  rx   r   	_kdf_saltr   _compat_entriesr9   r  r   r}   r   rQ   r   r   rz   r  get_stream_filterra   rL   rb   r   rO   )rW   r   
default_cfrJ   rJ   rK   r     s0   


z#PubKeySecurityHandler.as_pdf_objectc                 C   s0   | j  D ]}t|tsq|j|||d qd S )Nr  )r  standard_filtersra   rL   rp   )rW   re   rg   rf   r  rJ   rJ   rK   rp     s
   

z$PubKeySecurityHandler.add_recipientsrt   c           	      C   s   t |trt|}t |tstdt| d|}n|}t	 }| j
 D ])}t |ts0q(||}|jtjkr?|  S |j}|durQt |tsMJ ||M }q(t |trZ|| _ttj|S )a  
        Authenticate a user to this security handler.

        :param credential:
            The credential to use (an instance of :class:`.EnvelopeKeyDecrypter`
            in this case).
        :param id1:
            First part of the document ID.
            Public key encryption handlers ignore this key.
        :return:
            An :class:`AuthResult` object indicating the level of access
            obtained.
        zRPubkey authentication credential must be an instance of EnvelopeKeyDecrypter, not rv  N)ra   r<   r;   deserialiser<  r+   rb  typer@   r   r  r  rL   rw   statusr3   rs   permission_flags_credentialr2   rr   )	rW   rt   id1deser_credentialactual_credentialrg   r  r   cf_flagsrJ   rJ   rK   rw     s2   





z"PubKeySecurityHandler.authenticatec                 C   s   | j  jS r]   )r  get_for_stream
shared_keyr^   rJ   rJ   rK   get_file_encryption_key"  s   z-PubKeySecurityHandler.get_file_encryption_key)TNNTNr]   )2rE   rF   rG   r   r*   r   r  r  r  r  r  r   r5   rI   r  r9   ry   r@   r   rB   r   r   r   rH   r  r   r   listr   rV   r  r\  r   r  r  r4   r  r  r  r  r  r   rp   r
   r<  r<   r2   rw   r  r   rJ   rJ   rY   rK   rM     s   
 



	
`	C!!


2rM   )NT)T)abcenumloggingr  rk   rT  dataclassesr   hashlibr   r   typingr   r   r   r   r	   r
   
asn1cryptor   r   r   r   asn1crypto.algosr   asn1crypto.cmsr   r   asn1crypto.keysr   r   r   cryptography.hazmat.primitivesr   r   r   ,cryptography.hazmat.primitives.asymmetric.ecr   r   r   r   r   1cryptography.hazmat.primitives.asymmetric.paddingr   r   r   r   -cryptography.hazmat.primitives.asymmetric.rsar    r!   .cryptography.hazmat.primitives.asymmetric.x448r"   r#   0cryptography.hazmat.primitives.asymmetric.x25519r$   r%   "cryptography.hazmat.primitives.kdfr&   *cryptography.hazmat.primitives.kdf.x963kdfr'   ,cryptography.hazmat.primitives.serializationr(    r*   r+   _utilr-   r.   r/   r0   r1   apir2   r3   r4   r5   r6   r7   r8   r9   r:   cred_serr;   r<   filter_mixinsr=   r>   r?   permissionsr@   	getLoggerrE   rn  rB   ABCrL   r   r   r   r   r   DEF_EMBEDDED_FILEr   r   r   uniqueEnumr   r   r   r  r   r   r   HashAlgorithmr   r  r  r   r   r$  r7  rm   rb   r;  r<  SequencerC  rF  r  rP  r   rX  registerr6  r  rq   r  r  r  r  r  r  rM   rJ   rJ   rJ   rK   <module>   s<    ,
 







!


!
:

0
G;

  

B
?	