o
    >el                  
   @   sd  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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mZ d dlmZ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$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- ddl.m/Z/m0Z0 ddl1m2Z2m3Z3 eG dd dZ4dee5e6f de6fddZ7	d9de6de4dee6 fddZ8	d9de6de4de6dee6 fddZ9dddZ:de6fd d!Z;	d9de6d"e6dee6 de6fd#d$Z<ej=G d%d& d&ej>Z?G d'd( d(ej@e/ZAG d)d* d*e'e jBZCG d+d, d,eCe2ZDG d-d. d.eCe3ZEeFd/ZGd0d1 ZHd2d3 ZId4ejJfd5d6ZKe,jLG d7d8 d8e,ZMe/LeA dS ):    N)	dataclass)sha256sha384sha512)DictOptionalTupleUnion)core)Cipher
algorithmsmodes)genericmisc   )compute_o_value_legacycompute_o_value_legacy_prepcompute_u_value_r2compute_u_value_r34legacy_normalise_pw)aes_cbc_decryptaes_cbc_encrypt	as_signedrc4_encrypt)
	ALL_PERMS
AuthResult
AuthStatusCryptFilterCryptFilterBuilderCryptFilterConfigurationIdentityCryptFilterPdfKeyNotAvailableErrorSecurityHandlerSecurityHandlerVersion)SerialisableCredentialSerialisedCredential)AESCryptFilterMixinRC4CryptFilterMixinc                   @   s<   e Zd ZU eed< eed< eed< ededd fddZdS )	_R6KeyEntry
hash_valuevalidation_saltkey_saltentryreturnc                 C   s4   t |dksJ t|d d |dd |dd S )N0       (   )lenr(   )clsr,    r3   a/var/www/html/humari/django-venv/lib/python3.10/site-packages/pyhanko/pdf_utils/crypt/standard.py
from_bytes,   s   $z_R6KeyEntry.from_bytesN)__name__
__module____qualname__bytes__annotations__classmethodr5   r3   r3   r3   r4   r(   &   s   
 r(   passwordr-   c                 C   s8   t | tr| s	dS ddlm} || d} | d d S )N    r   )saslprepzutf-8   )
isinstancestr	_saslprepr>   encode)r<   r>   r3   r3   r4   _r6_normalise_pw2   s   
rD   pw_bytesr,   u_entryc                 C   s   t | |j|}||jkS N)_r6_hash_algor*   r)   )rE   r,   rF   purported_hashr3   r3   r4   _r6_password_authenticate=   s   
rJ   e_entryc                 C   s2   t | |j|}t|dksJ t||tdddS )Nr/      Fkeydataivuse_padding)rH   r+   r1   r   r9   )rE   r,   rK   rF   
interm_keyr3   r3   r4   _r6_derive_file_keyD   s
   rS   TF)T   F   input_bytesc                 C   s   t dd | D d S )Nc                 s   s    | ]}|d  V  qdS )   Nr3   .0br3   r3   r4   	<genexpr>V       z_bytes_mod_3.<locals>.<genexpr>rW   )sum)rV   r3   r3   r4   _bytes_mod_3T   s   r^   current_saltc                 C   s   t | }t|dksJ || |r t|dksJ || | }t ttf}d }}|dk s7||d kry| | |p=d d }t|dd ||dd d	d
d }	|t|	dd  }
|
|	 }|	t|	d  }|d7 }|dk s7||d ks7|dd S )u3   
    Algorithm 2.B in ISO 32000-2 § 7.6.4.3.4
       r.   r   @   r/   r=   NrL   FrM   r   )r   r1   updatedigestr   r   r   r^   )rE   r_   rF   initial_hashkhashesround_nolast_byte_valk1e	next_hashr3   r3   r4   rH   Y   s,   


rH   c                   @   sD   e Zd ZdZdZdZdZdZdZ	 de	j
fdd	Zedd
dZdS ) StandardSecuritySettingsRevisionz;Indicate the standard security handler revision to emulate.   rW         Nr-   c                 C   s    | j }|d u rt S t|S rG   )valuer   
NullObjectNumberObject)selfvalr3   r3   r4   as_pdf_object   s
   z.StandardSecuritySettingsRevision.as_pdf_objectc                 C   s$   zt |W S  ty   t j Y S w rG   )rl   
ValueErrorOTHER)r2   rp   r3   r3   r4   from_number   s
   

z,StandardSecuritySettingsRevision.from_number)r-   rl   )r6   r7   r8   __doc__	RC4_BASICRC4_EXTENDEDRC4_OR_AES128AES256rw   r   	PdfObjectru   r;   rx   r3   r3   r3   r4   rl   w   s    rl   c                   @   sX   e Zd ZdejfdejddifgZedefddZde	fdd	Z
ed
e	fddZdS )_PasswordCredential	pwd_bytesid1optionalTr-   c                 C   s   dS )Nr   r3   r2   r3   r3   r4   get_name   s   z_PasswordCredential.get_namec                 C   s   |   S rG   )dumprs   r3   r3   r4   
_ser_value   s   z_PasswordCredential._ser_valuerO   c                 C   s&   zt |W S  ty   tdw )Nz)Failed to deserialise password credential)r   loadrv   r   PdfReadError)r2   rO   r3   r3   r4   _deser_value   s
   
z _PasswordCredential._deser_valueN)r6   r7   r8   r
   OctetString_fieldsr;   rA   r   r9   r   r   r3   r3   r3   r4   r      s    r   c                       sX   e Zd ZU dZdZed ed< edd Z fddZ	d	e
fd
dZ fddZ  ZS )StandardCryptFilterzB
    Crypt filter for use with the standard security handler.
    NStandardSecurityHandler_handlerc                 C   s   t | jtr
| jjS trG   )r@   r   r   _auth_failedNotImplementedErrorr   r3   r3   r4   r      s   z StandardCryptFilter._auth_failedc                    s$   t |tstt | d | _d S rG   )r@   r   	TypeErrorsuper_set_security_handler_shared_key)rs   handler	__class__r3   r4   r      s   

z)StandardCryptFilter._set_security_handlerr-   c                 C   s   | j sJ | j  S rG   )r   get_file_encryption_keyr   r3   r3   r4   derive_shared_encryption_key   s   

z0StandardCryptFilter.derive_shared_encryption_keyc                    s   t   }t| j|d< |S )N/Length)r   ru   r   rr   keylenrs   resultr   r3   r4   ru      s   
z!StandardCryptFilter.as_pdf_object)r6   r7   r8   ry   r   r   r:   propertyr   r   r9   r   ru   __classcell__r3   r3   r   r4   r      s   
 
r   c                   @      e Zd ZdZdS )StandardAESCryptFilterz=
    AES crypt filter for the standard security handler.
    Nr6   r7   r8   ry   r3   r3   r3   r4   r          r   c                   @   r   )StandardRC4CryptFilterz=
    RC4 crypt filter for the standard security handler.
    Nr   r3   r3   r3   r4   r      r   r   z/StdCFc                 C      t tt| dittdS Nr   )default_stream_filterdefault_string_filter)r   STD_CFr   r   r3   r3   r4   _std_rc4_config   
   r   c                 C   r   r   )r   r   r   r   r3   r3   r4   _std_aes_config   r   r   cfdictc                 C   s   |  dd}t|d dS )Nr   r0   r`   r   )getr   )r   _acts_as_defaultkeylen_bitsr3   r3   r4   #_build_legacy_standard_crypt_filter   s   r   c                
       sz  e Zd ZU dZedeeddd eddd edd	d iZeeje	f e
d
< edefddZedddeddfdedefddZededfddZed2ddZ						d3dedededee f fddZed ejdefd!d"Zed ejfd#d$Zd%d& Zd'efd(d)Zd'efd*d+Z 	d4d'ee de!fd,d-Z"de#e$ee f fd.d/Z%defd0d1Z&  Z'S )5r   a  
    Implementation of the standard (password-based) security handler.

    You shouldn't have to instantiate :class:`.StandardSecurityHandler` objects
    yourself. For encrypting new documents, use :meth:`build_from_pw`
    or :meth:`build_from_pw_legacy`.

    For decrypting existing documents, pyHanko will take care of instantiating
    security handlers through :meth:`.SecurityHandler.build`.
    z/V2z/AESV2c                 C   
   t ddS )NrL   r   r   ___r3   r3   r4   <lambda>       z StandardSecurityHandler.<lambda>z/AESV3c                 C   r   )Nr/   r   r   r   r3   r3   r4   r     r   z	/Identityc                 C   s   t  S rG   )r    r   r3   r3   r4   r     s    _known_crypt_filtersr-   c                 C   s
   t dS )N	/Standard)r   
NameObjectr   r3   r3   r4   r     s   
z StandardSecurityHandler.get_nameNrL   Trevpermsc
                 K   sF  t |}|durt |n|}|tjkrt| d|tjkr"d}n	|r+|tjkr+d}t|||j|}t|d@ }|tjkrNt|dB }t||||\}}nt	||j|||||	\}}|tjkrdt
j}n|tjkrmt
j}nt
j}|tjkr|du r|rtdd}nt|d}| d
||||||||	d|
}||_t||d	|_|S )a  
        Initialise a legacy password-based security handler, to attach to a
        :class:`~.pyhanko.pdf_utils.writer.PdfFileWriter`.
        Any remaining keyword arguments will be passed to the constructor.

        .. danger::
            The functionality implemented by this handler is deprecated in the
            PDF standard. We only provide it for testing purposes, and to
            interface with legacy systems.

        :param rev:
            Security handler revision to use, see
            :class:`.StandardSecuritySettingsRevision`.
        :param id1:
            The first part of the document ID.
        :param desired_owner_pass:
            Desired owner password.
        :param desired_user_pass:
            Desired user password.
        :param keylen_bytes:
            Length of the key (in bytes).
        :param use_aes128:
            Use AES-128 instead of RC4 (default: ``True``).
        :param perms:
            Permission bits to set (defined as an integer)
        :param crypt_filter_config:
            Custom crypt filter configuration. PyHanko will supply a reasonable
            default if none is specified.
        :return:
            A :class:`StandardSecurityHandler` instance.
        Nz/ is not supported by this bootstrapping method.   rL       l    r   )versionrevisionlegacy_keylen
perm_flagsodataudatacrypt_filter_configencrypt_metadatar   r   r3   )r   rl   r|   rv   rz   r   rp   r   r   r   r#   RC4_40RC4_LONGER_KEYSr   r   r   r   _credential)r2   r   r   desired_owner_passdesired_user_passkeylen_bytes
use_aes128r   r   r   kwargso_entryrF   rN   r   shr3   r3   r4   build_from_pw_legacy  sx   -










	z,StandardSecurityHandler.build_from_pw_legacyc                 K   s  t |}|durt |n|}td}td}	td}
t||	}||	 |
 }t||
}t||tddd\}}t|dksAJ td}td}t|||}|| | }t|||}t||tddd\}}t|dksqJ td|d@ }|d	 |rd
nd d td }t	t
|t }| }|||  }| dtjtjd|||||||d
|}||_td|i|_|S )a  
        Initialise a password-based security handler backed by AES-256,
        to attach to a :class:`~.pyhanko.pdf_utils.writer.PdfFileWriter`.
        This handler will use the new PDF 2.0 encryption scheme.

        Any remaining keyword arguments will be passed to the constructor.

        :param desired_owner_pass:
            Desired owner password.
        :param desired_user_pass:
            Desired user password.
        :param perms:
            Desired usage permissions.
        :param encrypt_metadata:
            Whether to set up the security handler for encrypting metadata
            as well.
        :return:
            A :class:`StandardSecurityHandler` instance.
        Nr/   r`   rL   F)rQ   z<Ir   s      T   F   adbrn   )
r   r   r   r   r   r   oeseedueseedencrypted_permsr   r   r3   )rD   secretstoken_bytesrH   r   r9   r1   structpackr   r   AESr   ECB	encryptorrb   finalizer#   r}   rl   r   r   r   )r2   r   r   r   r   r   owner_pw_bytesuser_pw_bytesencryption_keyu_validation_salt
u_key_saltu_hashrF   u_interm_keyr   ue_seedo_validation_salt
o_key_salto_hashr   o_interm_keyoe_seedperms_bytesextd_perms_bytescipherr   r   r   r3   r3   r4   build_from_pw  sp   









z%StandardSecurityHandler.build_from_pwro   c                 C   s   t | t |  krdksn td| d|r+|r+t |t |  kr*dks4n td| d|r<t |dkrEtd| dd S )Nr.   z2/U and /O entries must be 48 bytes long in a rev. z security handlerr/   z;/UE and /OE must be present and be 32 bytes long in a rev. rL   z6/Perms must be present and be 16 bytes long in a rev. )r1   r   PdfError)r   r   r   r   r   r   r3   r3   r4   _check_r6_values  s&   &z(StandardSecurityHandler._check_r6_valuesr   r   r   r   c                    s  |d u r+|t jkrtd}n|t jkrt|}n|t jkr&|d u r&td}ntdt j	||||
|d || _
t|| _|tjkrW| j|||||	 || _|| _|	| _nt|t|  kredkskn tdd  | _ | _| _|| _|| _d | _d| _d S )Nr   r/   z1Could not impute a reasonable crypt filter config)r   compat_entrieszD/U and /O entries must be 32 bytes long in a legacy security handlerF)r#   r   r   r   r}   r   r   r   r   __init__r   r   r   rl   r   r   r   r   r   r1   r   r   r   r   )rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r3   r4   r     sH   









z StandardSecurityHandler.__init__encrypt_dictc                 C   s   | dd}|d dkrtd|d }z
|d }|d }W n ty+   tdw d	tjd
tfdd}t|t| dt	|j
dd |j
dd |d||d||d||jdtdddS )a  
        Gather and preprocess the "easy" metadata values in an encryption
        dictionary, and turn them into constructor kwargs.

        This function processes ``/Length``, ``/P``, ``/Perms``, ``/O``, ``/U``,
        ``/OE``, ``/UE`` and ``/EncryptMetadata``.
        r   r0   r`   r   z"Key length must be a multiple of 8/O/Uz!/O and /U entries must be presentxr-   c                 S   s,   t | tjtjfstdt|  | jS )NzExpected string, but got )r@   r   TextStringObjectByteStringObjectr   r   typeoriginal_bytes)r   r3   r3   r4   
_get_bytes?  s
   zFStandardSecurityHandler.gather_encryption_metadata.<locals>._get_bytes/PNr.   /OE/UE/Perms/EncryptMetadataT)default)r   r   r   r   r   r   r   r   )r   r   r   KeyErrorr   r~   r9   dictr   r   r   get_and_applybool)r2   r   r   r   r   r   r  r3   r3   r4   gather_encryption_metadata)  s.   




z2StandardSecurityHandler.gather_encryption_metadatac                 C   s>   t |d }t|d }td||| |d| |S )N/V/R)r   r   r   r3   )r#   rx   rl   r   process_crypt_filtersr  )r2   r   vrr3   r3   r4   instantiate_from_pdf_objectS  s   z3StandardSecurityHandler.instantiate_from_pdf_objectc                 C   s   t  }t d|d< t | j|d< t | j|d< t t| j|d< | j	s.| j
tjkr8t | jd |d< | j
 |d< | j |d	< | j
tjkr\t | j|d
< || j  | jtjkrzt | j|d< t | j|d< t | j|d< |S )Nr   z/Filterr   r   r  r`   r   r  r  r  r  r  r  )r   DictionaryObjectr   r   r   r   rr   r   r   _compat_entriesr   r#   r   r   ru   r   BooleanObjectr   rb   r   rl   r}   r   r   r   r   r3   r3   r4   ru   `  s*   z%StandardSecurityHandler.as_pdf_objectr   c                 C   st   | j }| j}|tjkrt|| j| j|\}}nt||j| j	| j| j|| j
\}}|d d }|d d }||k|fS )NrL   )r   r   rl   rz   r   r   r   r   rp   r   r   )rs   r   r<   r   
user_tokenuser_tok_suppliedrN   r3   r3   r4   _auth_user_password_legacyz  s$   

	z2StandardSecurityHandler._auth_user_password_legacyc                    s   t ||d}| j}t||j| j}|tjkrt|| j}n| j}t	dddD ] t
 fdd|D }t||}q'|}| ||\}	}|	rN|| _tj|fS | ||\}
}|
r`|| _tj|fS tjd fS )Nr      c                 3   s    | ]}| A V  qd S rG   r3   rX   ir3   r4   r[     r\   z?StandardSecurityHandler._authenticate_legacy.<locals>.<genexpr>)r   r   r   rp   r   rl   rz   r   r   ranger9   r  r   r   OWNERUSERFAILED)rs   r   r<   credr   rN   prp_userpassrt   new_keyowner_passworduser_passwordr3   r  r4   _authenticate_legacy  s&   



z,StandardSecurityHandler._authenticate_legacyc                 C   s   t |tr
t|}t |tttfstdt	| dt |tr,|d j
}|d j
}| j}|tjkr<| |\}}n|du rEtdt|}| ||\}}|durY|| _nd| _t|| jdS )	a  
        Authenticate a user to this security handler.

        :param credential:
            The credential to use (a password in this case).
        :param id1:
            First part of the document ID. This is mandatory for legacy
            encryption handlers, but meaningless otherwise.
        :return:
            An :class:`AuthResult` object indicating the level of access
            obtained.
        z]Standard authentication credential must be a string, byte string or _PasswordCredential, not .r   r   Nz+id1 must be specified for legacy encryptionT)statuspermission_flags)r@   r%   r$   deserialiser   rA   r9   r   r   r   nativer   rl   r}   _authenticate_r6r   r&  r   r   r   r   )rs   
credentialr   r   resrN   r3   r3   r4   authenticate  s0   





z$StandardSecurityHandler.authenticatec                 C   s.  t |}t| j}t| j}t||| jr$tj}t||| j	| j}nt||r4tj
}t||| j}ntjd fS tt|t }| }|| j|  }	|	dd dk}
|
| jtd|	d d d kM }
zt|	d  }|
|| jkM }
W n ty   d}
Y nw |
std	td
|i| _||fS )N	      r   z<irn   r   r`   FznFile decryption key didn't decrypt permission flags correctly -- file permissions may have been tampered with.r   ) rD   r(   r5   r   r   rJ   r   r  rS   r   r  r   r   r   r   r   r   r   	decryptorrb   r   r   r   r   unpack_EXPECTED_PERMS_8r   r  r   r   r   r   )rs   r<   rE   o_entry_splitu_entry_splitr   rN   r   r2  decrypted_p_entryperms_okdecr_metadata_flagr3   r3   r4   r,    s<   

"z(StandardSecurityHandler._authenticate_r6c                 C   s&   | j }|du rt| jrdd|S )aQ  
        Retrieve the (global) file encryption key for this security handler.

        :return:
            The file encryption key as a :class:`bytes` object.
        :raise misc.PdfReadError:
            Raised if this security handler was instantiated from an encryption
            dictionary and no credential is available.
        NzAuthentication failed.z7No key available to decrypt, please authenticate first.)r   r!   r   )rs   rN   r3   r3   r4   r     s   
z/StandardSecurityHandler.get_file_encryption_key)ro   )NNNTNTrG   )(r6   r7   r8   ry   r   r   r   r   r   r   r:   r;   rA   r   r   rl   intr   r   staticmethodr   r#   r   r   r   r  r	  r  r  ru   r9   r  r&  r   r/  r   r   r,  r   r   r3   r3   r   r4   r      s   
 
tZ;)
-,r   rG   )Nabcenumr   r   dataclassesr   hashlibr   r   r   typingr   r   r   r	   
asn1cryptor
   &cryptography.hazmat.primitives.ciphersr   r   r   pyhanko.pdf_utilsr   r   _legacyr   r   r   r   r   _utilr   r   r   r   apir   r   r   r   r   r   r    r!   r"   r#   cred_serr$   r%   filter_mixinsr&   r'   r(   rA   r9   rD   rJ   rS   r4  r^   rH   uniqueVersionEnumrl   Sequencer   ABCr   r   r   r   r   r   r   r  r   registerr   r3   r3   r3   r4   <module>   s    0





    *