U
    <g                     @   sb  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lAmBZBmCZCmDZD ddlEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZN ddlOmPZPmQZQ ddlRmSZSmTZTmUZU ddlVmWZW eXeYZZeddG dd dZ[G dd  d eHe j\Z]G d!d" d"e]eSZ^G d#d$ d$e]eTZ_G d%d& d&e]eUZ`e?ad'Zbe?ad(Zcdkd)d*Zddld+d,Zedmd-d.ZfejgG d/d0 d0ejhZidnejeWd1d2d3Zkeejlejd4d5d6Zmeejlejd4d7d8Znejlejejd9d:d;Zoeee!jpeef d<d=d>Zqeejrejd4d?d@ZsejreejejejdAdBdCZtejejue[dDdEdFZvdoeeju ejeWe[ejwdGdHdIZxG dJdK dKeyZzG dLdM dMZ{G dNdO dOej|Z}G dPdQ dQej|Z~edRZe!jpejeej e9dSdTdUZG dVdW dWe{ePZePe eje{eej dXdYdZZejwe{eeej eeW f d[d\d]Ze?jd^d_d`Zdadb Zdcdd Zdedf Zdgdh ZeLjG didj djeLZdS )p    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rc4_encrypt)	
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__rA   bool__annotations__rB    rH   rH   B/tmp/pip-unpacked-wheel-w101_d3s/pyhanko/pdf_utils/crypt/pubkey.pyr@   F   s   
r@   c                       s   e Zd ZU dZdZed ed< dddd fdd	
Zee	d
ddZ
 fddZe feej eedddZed
ddZed
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                   s6   || _ || _|| _d| _d  | _| _t jf | d S )NF)rM   rN   rO   _pubkey_auth_failed_shared_key_recp_key_seedsuper__init__)selfrM   rN   rO   kwargs	__class__rH   rI   rT   m   s    zPubKeyCryptFilter.__init__returnc                 C   s   | j S N)rP   rU   rH   rH   rI   _auth_failed|   s    zPubKeyCryptFilter._auth_failedc                    s*   t |tstt | d  | _| _d S r[   )
isinstancerK   	TypeErrorrS   _set_security_handlerrQ   rR   )rU   handlerrW   rH   rI   r`      s    
z'PubKeyCryptFilter._set_security_handler)certspolicypermsc                 C   sv   | j s| jrtd| jdkr2td| _g | _| jdk	sF| jdkrPt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.)rc   include_permissions)
rN   rM   r+   PdfErrorsecretstoken_bytesrR   rQ   construct_recipient_cmsappend)rU   rb   rc   rd   Znew_cmsrH   rH   rI   add_recipients   s&    
z PubKeyCryptFilter.add_recipientsc                 C   sB   | j D ]0}t||\}}|dk	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)rM   read_seed_from_recipient_cmsrR   r0   r1   USERFAILED)rU   
credentialrecpseedrd   rH   rH   rI   authenticate   s    
zPubKeyCryptFilter.authenticatec                 C   s   | j d k	st| jd kr"td| j jtjkr8t }nt	 }|
| j | jD ]}|
|  qP| jsz| jrz|
d | d | j S )Nz&No seed available; authenticate first.s   )rL   AssertionErrorrR   r+   rg   versionr7   AES256r   r   updaterM   dumprO   rN   digestkeylen)rU   Zmdrq   rH   rH   rI   derive_shared_encryption_key   s    



z.PubKeyCryptFilter.derive_shared_encryption_keyc                    sd   t   }t| jd |d< tdd | jD }| jrD||d< n|d |d< t| j	|d< |S )N   /Lengthc                 s   s   | ]}t | V  qd S r[   r*   ByteStringObjectrx   .0rq   rH   rH   rI   	<genexpr>   s    z2PubKeyCryptFilter.as_pdf_object.<locals>.<genexpr>/Recipientsr   /EncryptMetadata)
rS   as_pdf_objectr*   NumberObjectrz   ArrayObjectrM   rN   BooleanObjectrO   )rU   resultrM   rW   rH   rI   r      s    


zPubKeyCryptFilter.as_pdf_object)rC   rD   rE   __doc__rL   r   rG   rT   propertyrF   r]   r`   r>   allow_everythingr   r   Certificater@   rl   r0   rs   bytesr{   r   __classcell__rH   rH   rW   rI   rJ   V   s$   

+rJ   c                   @   s   e Zd ZdZdS )PubKeyAESCryptFilterz<
    AES crypt filter for public key security handlers.
    NrC   rD   rE   r   rH   rH   rH   rI   r      s   r   c                   @   s   e Zd ZdZdS )PubKeyAESGCMCryptFilterz@
    AES-GCM crypt filter for public key security handlers.
    Nr   rH   rH   rH   rI   r      s   r   c                   @   s   e Zd ZdZdS )PubKeyRC4CryptFilterz<
    RC4 crypt filter for public key security handlers.
    Nr   rH   rH   rH   rI   r      s   r   z/DefaultCryptFilterz/DefEmbeddedFilec                 C   s   t tt| d||dittdS NT)rz   rN   rM   rO   Zdefault_stream_filterZdefault_string_filter)r4   DEFAULT_CRYPT_FILTERr   rz   rM   rO   rH   rH   rI   _pubkey_rc4_config  s     r   c                 C   s   t tt| d||dittdS r   )r4   r   r   r   rH   rH   rI   _pubkey_aes_config!  s     r   c                 C   s   t ttd| |dittdS )NT)rN   rM   rO   r   )r4   r   r   rM   rO   rH   rH   rI   _pubkey_gcm_config0  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)	rC   rD   rE   r   r*   
NameObjectZS3S4S5rH   rH   rH   rI   r   >  s   

r   )rr   rd   c                 C   s$   t | dkst| |r| nd S )Nre       )lenrt   as_bytes)rr   rd   rf   rH   rH   rI   construct_envelope_contentJ  s    r   )pub_key_inforidenvelope_keyc                 C   sR   t  }tdtdi}t|  }t|ts6t	|j
||d}t|||dS )N	algorithmrsaes_pkcs1v15paddingr   algoencrypted_data)r   r   r   r   r   load_der_public_keyrx   r^   r!   rt   encrypt_format_ktri)r   r   r   r   r   pub_keyr   rH   rH   rI   _rsaes_pkcs1v15_recipientQ  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st|	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   Zpyhanko.sign.signers.pdf_cmsr   r   r   r   r   r   r   r   r   rx   r^   r!   rt   r   r   )r   r   r   r   r   Zdigest_function_namedigest_specr   r   r   r   rH   rH   rI   _rsaes_oaep_recipientb  s(    r   r   c              
   C   s   t dt d| ||diS )Nktrir   )ru   r   key_encryption_algorithmencrypted_key)r   RecipientInfoZKeyTransRecipientInfor   rH   rH   rI   r     s     r   )r   rZ   c                 C   s   | j }|dkr| jd }n|dkr(d}nd}|dkrJt tdtdfS |dkrht td	td
fS t tdtdfS d S )Necr)   x25519      Zaes128_wrapz1.3.132.1.11.1   Zaes192_wrapz1.3.132.1.11.2Zaes256_wrapz1.3.132.1.11.3)r   Zbit_sizer   SHA256r   SHA384SHA512)r   	algo_nameZapprox_sec_levelrH   rH   rI   _choose_ecdh_settings  s(    r   c                 C   s   t | \}}}td|i}t|  }t|trLt|j}|	t
 |}	n@t|trjt }|	|}	n"t|trt }|	|}	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_keyZkey_to_wrapr   r   originator_keyr   ukmr   )!r   r   r   r   rx   r^   r   generate_ec_private_keycurveexchanger   r%   r$   generater#   r"   NotImplementedErrorr   load
public_keypublic_bytesEncodingDERPublicFormatSubjectPublicKeyInforh   ri   _kdf_for_exchangederiver   Zaes_key_wrap_format_karir   )r   r   r   r   key_wrap_algo_idZkey_exch_algo_idr   r   r   
ecdh_valueZoriginator_key_infor   kdfZkekr   rH   rH   rI   _ecdh_recipient  sV    






 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   )ru   
originatorr   r   recipient_encrypted_keys)r   r   ZKeyAgreeRecipientInfoOriginatorIdentifierOrKeyZRecipientEncryptedKeyr   rH   rH   rI   r     s"     r   )r   certrc   c           
      C   s   |j }|d }|d j}t| dks(t|js\|j}|d ksFd|jkr\td|jj	 dt
|j|jd}|dkrt
d|i}|jrt||| S t||| S n2|d	krt
d|i}	t||	| S td
| dd S )Nr       key_enciphermentzCertificate for subject z8 does not have the 'key_encipherment' key usage bit set.)issuerserial_numberrsaZissuer_and_serial_number)r   r   x448zCannot encrypt for key type '')r   nativer   rt   rA   Zkey_usage_valuer+   ZPdfWriteErrorsubjectZhuman_friendlyr   IssuerAndSerialNumberr   r   RecipientIdentifierrB   r   r   KeyAgreementRecipientIdentifierr   r   )
r   r   rc   r   Zpubkey_algo_infoZalgorithm_nameZ	key_usageZiss_serial_ridr   Zka_ridrH   rH   rI   _recipient_info  s8    

r   )certificatesrr   rd   rc   rZ   c                    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)rf   r   )ivc                    s   g | ]}t  |d qS ))rc   )r   )r   r   r   rc   rH   rI   
<listcomp>X  s   z+construct_recipient_cms.<locals>.<listcomp>Z
aes256_cbcr   data)content_typecontent_encryption_algorithmencrypted_contentr   )ru   recipient_infosencrypted_content_infoenveloped_data)r  content)r   rh   ri   r.   r   ZEncryptionAlgorithmr   ZEncryptionAlgorithmIdZEncryptedContentInfoZContentTypeEnvelopedDataContentInfo)r  rr   rd   rc   rf   Zenvelope_contentr  encrypted_envelope_contentZ	rec_infosr   r
  r  rH   r  rI   rj   7  sH      
  

	rj   c                   @   s   e Zd ZdS )InappropriateCredentialErrorN)rC   rD   rE   rH   rH   rH   rI   r  ~  s   r  c                   @   sR   e Zd ZdZeejdddZee	j
edddZee	j
e	jeed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.
    rY   c                 C   s   t dS )zI
        :return:
            Return the recipient's certificate
        Nr   r\   rH   rH   rI   r     s    zEnvelopeKeyDecrypter.certr   algo_paramsrZ   c                 C   s   t dS )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.
        Nr  )rU   r   r  rH   rH   rI   decrypt  s    zEnvelopeKeyDecrypter.decryptr   r  originator_identifierr   rZ   c                 C   s   t dS )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.
        Nr  )rU   r   r  r  r   rH   rH   rI   decrypt_with_exchange  s    z*EnvelopeKeyDecrypter.decrypt_with_exchangeN)rC   rD   rE   r   r   r   r   r   r   r   r   r  r   r  rH   rH   rH   rI   r    s    r  c                   @   s   e Zd ZdefdejfgZdS )_PrivKeyAndCertkeyr   N)rC   rD   rE   r   r   r   _fieldsrH   rH   rH   rI   r    s   r  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suppPubInfor  r)   N)rC   rD   rE   r   r   OctetStringr  rH   rH   rH   rI   r    s   r  zaes(\d+)_wrap(_pad)?)r   r   r   rZ   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)r  r  r!  )r   lengthZ
sharedinfo)r   AES_WRAP_PATTERN	fullmatchr   intgroupr'   r  structpackrx   )r   r   r   r   Z
wrap_matchZkek_bit_lenrH   rH   rI   r     s"    


r   c                   @   s   e Zd ZdZedZeedddZ	e
dddZee
dd	d
ZejedddZeejdddZedddZedddZe
eje
dddZe
ejejee
 e
d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+)rY   c                 C   s   dS )NZraw_privkeyrH   clsrH   rH   rI   get_name  s    z#SimpleEnvelopeKeyDecrypter.get_namec                 C   s   | j | jd}t| S )N)r  r   )private_keyr   r  rx   )rU   valuesrH   rH   rI   
_ser_value  s    z%SimpleEnvelopeKeyDecrypter._ser_value)r  c              
   C   sZ   zt |}|d }|d }W n. tk
rL } ztd|W 5 d }~X Y nX t||dS )Nr  r   z-Failed to decode serialised pubkey credentialr   r/  )r  r   
ValueErrorr+   PdfReadErrorr+  )r-  r  decodedr  r   erH   rH   rI   _deser_value   s    
z'SimpleEnvelopeKeyDecrypter._deser_valuer2  c                 C   s   || _ || _d S r[   )r/  _cert)rU   r   r/  rH   rH   rI   rT     s    z#SimpleEnvelopeKeyDecrypter.__init__c                 C   s   | j S r[   )r8  r\   rH   rH   rI   r     s    zSimpleEnvelopeKeyDecrypter.certNc              
   C   sz   ddl m} z$|| |d}ddl m} ||}W n< tttfk
rl } ztjd|d W Y dS d}~X Y nX 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_infoNr2  )	keysr9  r;  IOErrorr3  r_   loggererrorr+  )key_file	cert_fileZkey_passphraser9  r/  r;  r   r6  rH   rH   rI   r     s     zSimpleEnvelopeKeyDecrypter.loadc              
   C   s   zTt |d}| }W 5 Q R X t||\}}}ddlm}m}	 ||}|	|}W nD ttt	fk
r }
 z t
jd| d|
d W Y dS d}
~
X Y nX 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`.
        rbr   ))_translate_pyca_cryptography_cert_to_asn1(_translate_pyca_cryptography_key_to_asn1zCould not open PKCS#12 file .r<  Nr2  )openreadr(   load_key_and_certificatesr>  rE  rF  r?  r3  r_   r@  rA  r+  )r-  Zpfx_filer:  fZ	pfx_bytesr/  r   Zother_certsrE  rF  r6  rH   rH   rI   load_pkcs120  s     
z&SimpleEnvelopeKeyDecrypter.load_pkcs12r  c           
      C   s   |d j }|dkrt }n|dkrddlm} |d }|d }|d j }|dkr`td	| d
tt||d d j d||d d j dd}ntd| dtj| j	
 dd}	t|	tst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/  rx   r^   r    r  r  )
rU   r   r  r   r   r   Zoaep_paramsr   Zmgf_namepriv_keyrH   rH   rI   r  Q  sF    



 
z"SimpleEnvelopeKeyDecrypter.decryptr  c                 C   s  |d }| j |j}d}|rJt t t t d|	dd}|sVt
dtj|d  }|d j}	t|	st
|	 d|	drtjntj}
t|||d	}|jd
krt
d|j }t| }tj| j dd}d}t|tr4t|tr|j j|j jkr$t!||"t# |}n`t|t$r`t|t%sTt!||"|}n4t|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   r#  Z_padr   r   z Only originator_key is supportedrM  zCOriginator's public key is not compatible with selected private keyz4The loaded key does not seem to be an EC private key)r   Zwrapped_key)*dhsinglepass_stddh_arc_patternr&  Zdottedr   SHA224r   r   r   getr(  r   r   r   r   rx   r   r%  endswithr   Zaes_key_unwrap_with_paddingZaes_key_unwrapr   r   chosenZuntagr   r   rO  r/  r^   r   r   r   r3  r   r   r$   r%   r"   r#   r  r   )rU   r   r  r  r   oidmatchr   r   r   Z
unwrap_keyr   Zoriginator_pub_key_infoZoriginator_pub_keyrP  Zmismatch_msgr   Zderived_kekrH   rH   rI   r    s     



 
z0SimpleEnvelopeKeyDecrypter.decrypt_with_exchange)N)N)rC   rD   rE   r   recompilerU  classmethodstrr.  r   r1  r7  r   r   r   rT   r   r   staticmethodr   rL  r   r   r  r   r   r  rH   rH   rH   rI   r+    s0   

! 8r+  )ed	decrypterrZ   c           
      C   s  | d D ]}|j dkr|j}|d j}t|tjs<td|d }|d j}|jj|kr|jj	|krz|
|d j|d W   S  tk
r } z|W 5 d }~X Y n. tk
r } ztd	|W 5 d }~X Y nX 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rz0|j|	d j|d |d |d jdW     S  tk
r } z|W 5 d }~X Y q tk
r } ztd	|W 5 d }~X Y qX qqtdq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   )r  r   zLRecipientInfo must be of type KeyTransRecipientInfo or KeyAgreeRecipientInfo)r   rY  r^   r   r   r   r   r   r   r   r  r  	Exceptionr+   r4  r  )
ra  rb  Zrec_infor   Zissuer_and_serialr   serialr6  r   Zrecipient_enc_keyrH   rH   rI   read_envelope_key  sx    









re  )recipient_cmsrb  rZ   c              	   C   s  | d j }|dkr td| | d }|d }t||}|d krFdS |d }|d j }z
|j}W n" ttfk
r   |d	 j }Y nX |d
krtd|dkrt}	|j	}
|	|||
}n&|dkrt
||}ntd| d|d d }d }t|dkrt|dd  }||fS )Nr  r  z7Recipient CMS content type must be enveloped data, not r  r
  )NNr  r  r   )ZdesZ	tripledesZrc2z@Support for DES, 3DES and RC2 has been dropped in pyHanko 0.26.0ZaesZrc4zCipher z is not allowed in PDF 2.0.re      )r   r+   r4  re  Zencryption_cipherr3  KeyErrorr   r-   Zencryption_ivr/   r   r>   
from_bytes)rf  rb  r  ra  r
  r   r   r  Zcipher_nameZdecryption_funr  r  rr   rd   rH   rH   rI   rm   5  sP    



rm   )cfdictc                 C   sb   z| d }W n t k
r*   tdY nX t|tjr>|f}dd |D }| dd}||dS )Nr   z.PubKey CF dictionary must have /Recipients keyc                 S   s   g | ]}t j|jqS rH   r   r  r   original_bytesr   xrH   rH   rI   r  w  s    z0_read_generic_pubkey_cf_info.<locals>.<listcomp>r   Tr   )rh  r+   r4  r^   r*   r   rW  )rj  rM   recipient_objsrO   rH   rH   rI   _read_generic_pubkey_cf_infon  s    
rp  c                 C   s(   |  dd}tf |d |dt| S )Nr}   (   r|   rz   rN   )rW  r   rp  )rj  rN   keylen_bitsrH   rH   rI   _build_legacy_pubkey_cf~  s    rt  c                 C   s   t f d|dt| S )Nr   rr  r   rp  rj  rN   rH   rH   rI   _build_aes128_pubkey_cf  s    rw  c                 C   s   t f d|dt| S )Nr   rr  ru  rv  rH   rH   rI   _build_aes256_pubkey_cf  s    rx  c                 C   s   t f d|it| S )NrN   )r   rp  rv  rH   rH   rI   _build_aesgcm_pubkey_cf  s
    ry  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eej eeed dddZd0eeed ee ee d fddZeedddZee e dddZ!eej"ee#dddZ$eej"ed d fddZ%eej"dd d!Z&eej"dd"d#Z'eej"dd$d%Z(d&d' Z)e e feej eed(d)d*Z*d1e+e,e-f e.d+d,d-Z/edd.d/Z0  Z1S )2rK   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[   )r5   )___rH   rH   rI   <lambda>  r   zPubKeySecurityHandler.<lambda>_known_crypt_filtersr   T)rb   rd   rc   pdf_macrZ   c
                 K   s   |r
t jnt j}d}|tjkr@|r2td|dd}nt|d|d}|	rf|tjkrf|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   )rO   rM   r   r   )rO   crypt_filter_configro  kdf_saltrd   rc   )r   r   r   r7   RC4_OR_AES128r   r   rv   r>   ZTOLERATE_MISSING_PDF_MACrh   ri   rl   )r-  rb   Zkeylen_bytesru   Zuse_aesZuse_crypt_filtersrd   rO   rc   r~  rV   	subfiltercfcr  shrH   rH   rI   build_from_certs  sF    8
  
z&PubKeySecurityHandler.build_from_certsNr4   )ru   pubkey_handler_subfilterr  ro  r  c	           	         s   |t jkr|tjkrtd|d kr|t jkr@td||d}nV|t jkrZt|||d}n<|t j	krrt
||d}n$|t jkrtd||d}n
tdt j||||||d || _|| _d | _d S )NzESubfilter /adbe.pkcs7.s5 is required for security handlers beyond V4.   )rz   rO   rM   r   r   z1Failed to impute a reasonable crypt filter config)rO   compat_entriesr  )r7   r  r   r   r+   rg   ZRC4_40r   RC4_LONGER_KEYSZAES_GCMr   rv   r   rS   rT   r  rO   rQ   )	rU   ru   r  legacy_keylenrO   r  ro  r  r  rW   rH   rI   rT   
  sZ    


 
zPubKeySecurityHandler.__init__rY   c                 C   s
   t dS )Nz/Adobe.PubSec)r*   r   r,  rH   rH   rI   r.  M  s    zPubKeySecurityHandler.get_namec                 C   s   dd t D S )Nc                 S   s   h | ]
}|j qS rH   )r   rm  rH   rH   rI   	<setcomp>S  s     zCPubKeySecurityHandler.support_generic_subfilters.<locals>.<setcomp>)r   r,  rH   rH   rI   support_generic_subfiltersQ  s    z0PubKeySecurityHandler.support_generic_subfilters)rj  rN   rZ   c                 C   s$   t | j||}|d kr td|S )NzJAn absent CFM or CFM of /None doesn't make sense in a PubSec CF dictionary)r8   r}  r+   r4  )r-  rj  rN   cfrH   rH   rI   read_cf_dictionaryU  s      z(PubKeySecurityHandler.read_cf_dictionary)encrypt_dictrZ   c                    sT   t  |}| |}|d k	r4|tjkr4tdn|d krP|tjkrPtd|S )Nz=Crypt filters require /adbe.pkcs7.s5 as the declared handler.z./adbe.pkcs7.s5 handler requires crypt filters.)rS   process_crypt_filters_determine_subfilterr   r   r+   r4  )r-  r  r  r  rW   rH   rI   r  c  s    
z+PubKeySecurityHandler.process_crypt_filters)r  c              	   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   s   g | ]}t j|jqS rH   rk  rm  rH   rH   rI   r    s     zSPubKeySecurityHandler.gather_pub_key_metadata.<locals>.<lambda>.<locals>.<listcomp>rH   )lstrH   rH   rI   r|    r   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[   )r^   r*   ZTextStringObjectr   rl  )rn  rH   rH   rI   r|    s     
)r  ro  rO   r  )rW  r+   rg   get_and_applyrF   dict)r-  r  rs  rz   rM   rO   rH   rH   rI   gather_pub_key_metadatau  s.    
  z-PubKeySecurityHandler.gather_pub_key_metadatac                 C   sP   z$t j|dtd|krtjntjdW S  tk
rJ   t d|d  Y nX d S )N
/SubFilterz/CFr  z8Invalid /SubFilter in public key encryption dictionary: )r+   r  r   r   r   r3  r4  )r-  r  rH   rH   rI   r    s    
z*PubKeySecurityHandler._determine_subfilterc                 C   s6   t |d }tf || || |d| |S )N/V)ru   r  r  )r7   Zfrom_numberrK   r  r  r  )r-  r  vrH   rH   rI   instantiate_from_pdf_object  s    z1PubKeySecurityHandler.instantiate_from_pdf_objectc                 C   s   t  }t |  |d< | jj|d< | j |d< | jrJt 	| j|d< | j
s\| jtjkrpt | jd |d< | jtjkrt | j|d< | jtjkr|| j  n0|  }t|tstt dd	 |jD |d
< |S )Nz/Filterr  r  r  r|   r}   r   c                 s   s   | ]}t | V  qd S r[   r~   r   rH   rH   rI   r     s   z6PubKeySecurityHandler.as_pdf_object.<locals>.<genexpr>r   )r*   DictionaryObjectr   r.  r  r   ru   r   Z	_kdf_saltr   Z_compat_entriesr7   r  r   rz   r   rO   r   r   rw   r  Zget_stream_filterr^   rJ   r_   r   rM   )rU   r   Z
default_cfrH   rH   rI   r     s0    


z#PubKeySecurityHandler.as_pdf_object)rb   rd   rc   c                 C   s0   | j  D ] }t|tsq
|j|||d q
d S )Nr  )r  standard_filtersr^   rJ   rl   )rU   rb   rd   rc   r  rH   rH   rI   rl     s    

z$PubKeySecurityHandler.add_recipients)rp   rZ   c           	      C   s   t |tr:t|}t |ts4tdt| d|}n|}t	 }| j
 D ]R}t |ts`qP||}|jtjkr~|  S |j}|dk	rPt |tst||M }qPt |tr|| _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 rG  N)r^   r:   r9   Zdeserialiser  r+   r4  typer>   r   r  r  rJ   rs   statusr1   ro   Zpermission_flagsrt   Z_credentialr0   rn   )	rU   rp   Zid1Zdeser_credentialZactual_credentialrd   r  r   Zcf_flagsrH   rH   rI   rs     s,    






z"PubKeySecurityHandler.authenticatec                 C   s   | j  jS r[   )r  Zget_for_streamZ
shared_keyr\   rH   rH   rI   get_file_encryption_key  s    z-PubKeySecurityHandler.get_file_encryption_key)TNNTN)N)2rC   rD   rE   r   r*   r   rt  rw  rx  ry  r}  r   r3   rG   r^  r7   rv   r>   r   r@   r   r   r   rF   r  r   r   listr   rT   r_  r.  r   r  r  r2   r  r  r  r  r  r   rl   r
   r  r:   r0   rs   r  r   rH   rH   rW   rI   rK     s   
     `     C !! 
2rK   )NT)NT)NT)T)T)abcenumloggingr\  rh   r)  dataclassesr   hashlibr   r   typingr   r   r   r   r	   r
   Z
asn1cryptor   r   r   r   Zasn1crypto.algosr   Zasn1crypto.cmsr   r   Zasn1crypto.keysr   r   r   Zcryptography.hazmat.primitivesr   r   r   Z,cryptography.hazmat.primitives.asymmetric.ecr   r   r   r   r   Z1cryptography.hazmat.primitives.asymmetric.paddingr   r   r   r   Z-cryptography.hazmat.primitives.asymmetric.rsar    r!   Z.cryptography.hazmat.primitives.asymmetric.x448r"   r#   Z0cryptography.hazmat.primitives.asymmetric.x25519r$   r%   Z"cryptography.hazmat.primitives.kdfr&   Z*cryptography.hazmat.primitives.kdf.x963kdfr'   ,cryptography.hazmat.primitives.serializationr(    r*   r+   _utilr-   r.   r/   apir0   r1   r2   r3   r4   r5   r6   r7   r8   Zcred_serr9   r:   Zfilter_mixinsr;   r<   r=   permissionsr>   	getLoggerrC   r@  r@   ABCrJ   r   r   r   r   r   ZDEF_EMBEDDED_FILEr   r   r   uniqueEnumr   r   r   r   r   r   r   HashAlgorithmr   r   r   r   r   r   r  rj   r_   r  r  Sequencer  r  r]  r%  r   r+  registerr  re  rm   r  rp  rt  rw  rx  ry  rK   rH   rH   rH   rI   <module>   s    ,
 




  "
";0 G;
  
 C 9	