)EjVdZddlZddlZddlZddlZddlZddlmZddlm Z ddl m Z ddl m Z mZmZmZmZmZmZddlmZmZdd lmZdd lmZmZmZmZmZ dd l m!Z!m"Z"dd l#m$Z$m%Z%dd l&m'Z'dZ(n#e)$r Z*e*Z(YdZ*[*ndZ*[*wwxYwe rddl+m,Z,ej-e.Z/GddZ0GddZ1GddeZ2GddZ3dee4e5fde4fdZ6de7de7fdZ8dS)aJ Utilities to perform encryption following the PDF standards. The contents of this module are internal to fpdf2, and not part of the public API. They may change at any time without prior warning or any deprecation period, in non-backward-compatible ways. Usage documentation at: N)hexlify) BOM_UTF16_BEurandom) TYPE_CHECKINGCallableIteratorOptionalSequenceTypeUnion)AccessPermissionEncryptionMethod) FPDFException)Name PDFObject PDFStringbuild_obj_dictcreate_dictionary_string)Ciphermodes)AES128AES256)PKCS7)FPDFceZdZdZdZdedeefdZdeede efdZ dedee zdeefd Z d S) ARC4az This is a simplified version of the ARC4 (alleged RC4) algorithm, created based on the following sources: * Wikipedia article on RC4 * github.com/manojpandey/rc4 (MIT License) * http://people.csail.mit.edu/rivest/pubs/RS14.pdf Having this ARC4 implementation makes it possible to have basic encryption functions without additional dependencies keyreturnct|}tt|j}d}t|jD]8}|||z|||zz|jz}||||c||<||<9|S)Nr)lenlistrangeMOD)selfr key_lengthSjis AC:\PYTHON\MyICR_Suite\python\Lib\site-packages\fpdf/encryption.pyKSAzARC4.KSA?sXX tx ! ! tx $ $AQqTCJ//48;A1qtJAaD!A$$r)c#Kd}d} |dz|jz}|||z|jz}||||c||<||<|||||z|jz}|V[)NrTr)r&)r'r)r+r*Ks r,PRGAz ARC4.PRGAHs   Q$("AQqTTX%A1qtJAaD!A$1Q4!A$;$(*+AGGG  r.textc|||}g}|D]'}||t|z (|SN)r1r-appendnext)r'r r2 keystreamrescs r,encryptz ARC4.encryptRsVIIdhhsmm,,  , ,A JJq4 ??* + + + + r.N) __name__ __module__ __qualname____doc__r&bytesr$intr-r r1 bytearrayr:r.r,rr1s   Cucd3iHSM5 (9d3ir.rc<eZdZdZdededdffd ZdefdZxZS) CryptFilterzMRepresents one crypt filter, listed under CF inside the encryption dictionarymodelengthr!Ncttd|_t||_t |dz |_dS)NrD)super__init__rtypec_f_mr@rF)r'rErF __class__s r,rJzCryptFilter.__init__]sJ '' $ZZ &1*oo r.crtfdtD}t|S)Nc2i|]}|t|SrB)getattr).0r r's r, z)CryptFilter.serialize..ds%"P"P"Ps3c(:(:"P"P"Pr.)rdirpdf_dict)r'obj_dicts` r, serializezCryptFilter.serializecs9!"P"P"P"Pc$ii"P"P"PQQ!!!r.) r;r<r=r>strr@rJrV __classcell__rMs@r,rDrDZssWW&S&#&$&&&&&& "3""""""""r.rDc$eZdZdZdfd ZxZS)EncryptionDictionaryz This class represents an encryption dictionary PDF 32000 reference - Table 20 The PDF trailer must reference this object (/Encrypt) security_handlerStandardSecurityHandlerr!Ncttd|_|j|_|j|_d|j d|_d|j d|_ |jdkrfd|j d|_ d|j d|_d|j d|_|j|_t%|j|_|jsd|_|jr-t/d|ji|_|jt6jkr*td|_td|_dStd|_td|_dS) NStandard<>falsez/StdCFIdentityStdCF)rIrJrfilterr(rFrevisionroupperuoeo_eueu_epermsversionvint32access_permissionpencrypt_metadatacfrTrVc_fencryption_methodr NO_ENCRYPTIONstm_fstr_f)r'r\rMs r,rJzEncryptionDictionary.__init__os :&& &1 !*2%'--//2222%'--//222  $ ) )9+.4466999DH9+.4466999DH>-399;;>>>DJ!)'9::0 ,$+D !   M+;+>+H+H+J+J KLLDH  -1A1O O Oj))DJj))DJJJgDJgDJJJr.)r\r]r!N)r;r<r=r>rJrXrYs@r,r[r[hsG ''''''''''r.r[c FeZdZdZdZdejejdfddde de e d e ezd ed e f d Z d e ddfdZdefdZdee eefde dee effdZde de de fdZdeezde defdZde fdZdeezde dee fdZdedeezdefdZededde defdZededde defd Zd!e defd"Zde fd#Z de fd$Z!eefdedd%eezd&ed'eezdef d(Z"d-d)Z#d-d*Z$d-d+Z%defd,Z&dS).r]a This class is referenced in the main PDF class and is used to handle all encryption functions * Calculate password and hashes * Provide encrypt method to be called by stream and strings * Set the access permissions on the document s (N^NuAdNV..h>/ dSizNFfpdfrowner_password user_password permissionryrvcJ||_d|z|_||_|r|nd|_||_d|_d|_tr6|jtj tj fvrtdt|jtj kr?d|_ d|_ |dtd|j|_n|jtj krFd |_ d |_ |d d |_td |j|_nw|jtjkr?d|_ d|_ |dtd|j|_n#d|_ d|_ |d||_dS)Nlpzucryptography module not available - Try: 'pip install cryptography' or use RC4 encryption method - Import error was: z1.6AESV2)rErFrbz2.0rAESV3V2z1.5)r~rtrrryrwr( import_errorrAES_128AES_256EnvironmentErrorrqrg_set_min_pdf_versionrDrzrv)r'r~rrrryrvs r,rJz StandardSecurityHandler.__init__s !Cj!P,.;C]]!2  D2  $  $7   #7(477   !%5%= = =DLDM  % %e , , ,!wtGGGDGG  #'7'? ? ?DLDM  % %e , , ,!DO!wtGGGDGG  #'7'E E EDLDM  % %e , , ,!tDODDDDGGDLDM  % %e , , ,!1r.file_idr!c||_|dd|_|jdkrX|d|_|||dS||_ | |_| |_ dS)z,File_id is the first hash of the PDF file idr!rb N) rinfo_idrgget_random_byteskgenerate_user_password_rev6generate_owner_password_rev6generate_perms_rev6generate_owner_passwordrigenerate_encryption_keygenerate_user_passwordrk)r'rs r,generate_passwordsz*StandardSecurityHandler.generate_passwordss qt} =A  **2..DF  , , . . .  - - / / /  $ $ & & & & &1133DF1133DF0022DFFFr.c t|S)zReturn an encryption dictionary)r[r's r,get_encryption_objz*StandardSecurityHandler.get_encryption_objs#D)))r.r2obj_idctd|t|ttfr|||n|||S)zOMethod invoked by PDFObject and PDFContentStream to encrypt strings and streamsz Encrypting %s)LOGGERdebug isinstancer?rAencrypt_streamencrypt_string)r'r2rs r,r:zStandardSecurityHandler.encrypts^  _d+++$ 233 3D  f - - -$$T622 r.stringc t|jtjkr#t|dSt d| |ddt| |d| dS#t$redtt| t|dz|ddcYSwxYw)NF)r:zEncrypting string: %szlatin-1r`raz utf-16-be)ryrrzrrVrrencoder? encrypt_byteshexrjUnicodeEncodeErrorrrArdecode)r'rrs r,rz&StandardSecurityHandler.encrypt_stringsD  !%5%C C CVU333==?? ? ,f555 F MM) $ $ $cuT// i0H0H&QQRRVVXX^^``ccc c! F F FFwy););L6==YdKeKe  !%5%C C C== T''77888r.c@|jtjtjfvSr4)ryrrrrs r,is_aes_algorithmz(StandardSecurityHandler.is_aes_algorithms#%  $  $*   r.datacDtjdd}||j||dzddd|dd dd|r$|t gd |}|r|||St ||S) a PDF32000 reference - Algorithm 1: Encryption of data using the RC4 or AES algorithms Append object ID and generation ID to the key and encrypt the data Generation ID is fixed as 0. Will need to revisit if the application start changing generation ID md5Fusedforsecurityirlittle byteordersignedrr)sAlT) hashlibnewupdaterto_bytesrr?digestencrypt_AES_cryptographyrr:)r'rrhr s r,rz%StandardSecurityHandler.encrypt_bytess Ku 5 5 5   h  ( (hu ( M M      ! !!x ! F F     " " 6 HHU33344 5 5 5hhjj  " " <00d;; ;vv~~c4(((r.r czt|d}td}||}||z }|jtjkr/tt|tj |n3tt|jtj |}|}|||z}|||S)zDEncrypts an array of bytes using AES algorithms (AES 128 or AES 256)r)rArrpadderrfinalizeryrrrrrCBCrr encryptorextend)r'r rivr padded_datacipherrs r,rz0StandardSecurityHandler.encrypt_AES_cryptographyst,,R00 1 1s""$$mmD)) v((( %)9)AAA 6#;; " . . .tv " 66  $$&&  ,,y/A/A/C/CC $ r.clssizec t|S)z https://docs.python.org/3/library/os.html#os.urandom os.urandom will use OS-specific sources to generate random bytes suitable for cryptographic use r)rrs r,rz(StandardSecurityHandler.get_random_bytes!st}}r.cdtdtfdt|dkrtSdfd|D}tjd|}dtdtfd}|D] }||rtd |d !d td ttgtfdtfd }||tj rp||tj rtd |dtj |drtj |dstd |dt|dkr |dd}| dS)al PDF2.0 - ISO 32000-2:2020 All passwords for revision 6 shall be based on Unicode. Preprocessing of a user-provided password consists first of normalizing its representation by applying the "SASLPrep" profile (Internet RFC 4013) of the "stringprep" algorithm (Internet RFC 3454) to the supplied password using the Normalize and BiDi options. Next, the password string shall be converted to UTF-8 encoding, and then truncated to the first 127 bytes if the string is longer than 127 bytes Python offers a stringprep module with the tables mapped in methods charr!cf|sdStj|rdStj|rdS|S)Nr ) stringprep in_table_b1 in_table_c12rs r,char_mapz8StandardSecurityHandler.prepare_string..char_map8sD r%d++ r&t,, xKr.rrc3.K|]}|VdSr4rB)rQr9rs r, z9StandardSecurityHandler.prepare_string..Fs+!>!>!((1++!>!>!>!>!>!>r.NFKCcjtj|ptj|ptj|pwtj|pctj|pOtj|p;tj|p'tj|ptj |Sr4) rrin_table_c21_c22 in_table_c3 in_table_c4 in_table_c5 in_table_c6 in_table_c7 in_table_c8 in_table_c9rs r, is_prohibitedz=StandardSecurityHandler.prepare_string..is_prohibitedLs'-- 0.t44 0)$// 0)$// 0)$// 0 )$// 0 ) 0) 0)$// r.z The password z contains prohibited charactersrfunc:tfd|DS)Nc3.K|]}|VdSr4rB)rQrrs r,rzPStandardSecurityHandler.prepare_string..has_character..es+44Tss4yy444444r.)any)rrs `r, has_characterz=StandardSecurityHandler.prepare_string..has_characterds&4444V44444 4r.z+ contains invalid bidirectional characters.rNzUTF-8)rWr#r?join unicodedata ucd_3_2_0 normalizeboolrrr in_table_d1 in_table_d2r)rrprepared_stringrrrrs @r,prepare_stringz&StandardSecurityHandler.prepare_string*s 3 3     v;;??77N''!>!>!>!>v!>!>!>>>&/99&/RR      "$  D}T"" #KFKKK   5# 5HcUD[,A 5d 5 5 5 5 =**@ A A }_j.DEE #WFWWW &q'9:: *?2+>?? $WFWWW   # % %-dsd3O%%g...r.passwordct|dkr |dd}t|d}||jddt|z |S)z PDF32000 reference - Algorithm 2: Computing an encryption key Step (a) - Add the default padding at the end of provided password to make it 32 bit long rNlatin1)r#rArrDEFAULT_PADDING)r'rrus r,padded_passwordz'StandardSecurityHandler.padded_password|sh x==2  }H hooh// 0 0 %oc!ffo6777r.c*t||j}tdD]}t |}|dt j|jdz }||j}tdD]]}g}|D]}| ||z tt t||}^t| S)z PDF32000 reference - Algorithm 3: Computing the encryption dictionary's O (owner password) value The security handler is only using revision 3 or 4, so the legacy r2 version is not implemented here 3NrH)r?rrr%rmathceilr(rr5rArr:r)r'm_rc4keyresultr+new_keyrs r,rz/StandardSecurityHandler.generate_owner_passwords $&&t':;; < <r  AAAA5di! 34456%%d&899r G GA!#G & &q1u%%%%tvv~~eGnnfEEFFFFV}}  """r.ctjdd}|tj|t jt|j }tdD]]}g}|D]}| ||z tt t |^fdtdDt S)z PDF32000 reference - Algorithm 5: Computing the encryption dictionary's U (user password) value The security handler is only using revision 3 or 4, so the legacy r2 version is not implemented here rFrrc3DK|]}|j|z VdSr4)r)rQxrr's r,rzAStandardSecurityHandler.generate_user_password..sE  67VAY-a0 0      r.r)rrrrArr?fromhexrrrr%r5rr:rr)r'rr r+r rrs` @r,rz.StandardSecurityHandler.generate_user_passwords? Ku 5 5 5 4/00111 t|,,---188::&&fr G GA!#G & &q1u%%%%tvv~~eGnnfEEFFFF      ;@99      V}}  """r.input_passwordsaltuser_keyctj||z|z}d} |dz }||z|z}tt |ddt j|dd}|}||dz| z} t| dddz} | dkr'tj| }nS| dkr'tj | }n&tj | }|dkr| d |dz krn?|ddS) zz Algorithm 2B - section 7.6.4.3.4 of the ISO 32000-2:2020 Applied on Security handlers revision 6 rTrNrr@rr) rsha256rrrrrrrrsumsha384sha512) rrrrr round_numberk1rre remainders r, compute_hashz$StandardSecurityHandler.compute_hashsi N>D08; < < C C E E   A L!#h.BF1SbS6NNEIa2h,?,?@@F((**I  b))I,>,>,@,@@AAcrcF aIA~~N1%%,,..aN1%%,,..N1%%,,..r!!ae|b/@&@&@' *"v r.c^||j}|st}|d}|d}||||z|z}||_|||}tt|tj d}| }| |j |z}||_dS)z Generating the U (user password) and UE (user encryption) for security handlers of revision 6 Algorithm 8 - Section 7.6.4.4.7 of the ISO 32000-2:2020 rH)rrN)rrrArrrrkrrrrrrrrrn) r'ruser_validation_salt user_key_saltrkr rrrns r,rz3StandardSecurityHandler.generate_user_password_rev6s ,0+>+>t?Q+R+R  (%KKM#44Q77--a00   ]AU  V V" #  }=QQs UY|%<%<==$$&&   df % % (:(:(<(< <&&((r.c||j}|std|j|d}|d}|||t |j|z|z}||_ |||t |j}tt|tj d}|}||j|z}||_dS)z Generating the O (owner password) and OE (owner encryption) for security handlers of revision 6 Algorithm 9 - Section 7.6.4.4.8 of the ISO 32000-2:2020 zInvalid owner password rH)rrrrN)rrrrrr?r rkrrirrrrrrrrrl) r'rowner_validation_saltowner_key_saltrir rrrls r,rz4StandardSecurityHandler.generate_owner_password_rev6sY ,,T-@AA Q O$:M O OPP P $ 5 5a 8 8..q11   -*tv..    $  $    )]]46**    s UY|%<%<==$$&&   df % % (:(:(<(< <&&((r.cd|jz}|jrdnd}|ddd|zdz|d z}t t |jtj}| }| || z}| |_ d S) u 7.6.4.4.9 Algorithm 10: Computing the encryption dictionary’s Perms (permissions) value (Security handlers of revision 6) of the ISO 32000-2:2020 lTFrHrFrsadbrN)rtrvrrrrrrECBrrrrrp)r'perms64brv perms_inputrrrps r,rz+StandardSecurityHandler.generate_perms_rev6 s &(>>#'#8B44d   a8E  B B  ##A&& ' tv 44$$&&   -- 0B0B0D0DDYY[[ r.ctjdd}|||j|t |j||jdz ddd|t |j |j dur/|j dkr$|t gd| d tj|jd z }t#d D]3}t%|d tj|jd z }4|S) zU PDF32000 reference Algorithm 2: Computing an encryption key rFrrrr)r+r+r+NrH2)rrrrrr?r rirtrrrvrqrrrr(r%r)r'rrrs r,rz/StandardSecurityHandler.generate_encryption_keysc Ku 5 5 5 %%d&899::: tv&&'''   #j 0 : :Xe ;     t|,,---  E ) )dla.?.? HHU33344 5 5 5>ty1)<==>?r E EA[[!CDIdo.A$B$B!CDFF r.)r!N)'r;r<r=r>rrallrRC4rWr r@rrJrr[rr rAr?r:rrrr rr classmethodr rrrrrrrrrrrBr.r,r]r]s V(,-A-=-A-C-C.>.B!&11111111 } 11 ** 11 , 1111111111f 3# 3$ 3 3 3 3*$8****  #y%/0  :=  sEz      FSF#F#FFFF9UY%6999999  $    )%)"3)S)Xc])))), % 1 $d#<=SU[O/D!:;O/SO/UO/O/O/[O/b      #####"#####( '0ikk !! + ,! )!!)# !  !!![!F0B!!!!&r.r]rr!ctjdd}|||S)NrFr)rrrr)rrs r,rr2s3 E5111AHHTNNN 88::r.nc|dz}|dz dz S)z%convert long to signed 32 bit integerr*lrB)r1s r,rsrs8s JA Nj ((r.)9r>rloggingrrrbinasciircodecsrosrtypingrrr r r r r enumsrrerrorsrsyntaxrrrrrrT&cryptography.hazmat.primitives.ciphersrr1cryptography.hazmat.primitives.ciphers.algorithmsrr&cryptography.hazmat.primitives.paddingrr ImportErrorerrorr~r getLoggerr;rrrDr[r]r?rArr@rsrBr.r,rAs UUUUUUUUUUUUUUUUUU55555555!!!!!!DDDDDDDDPPPPPPPP<<<<<<LLLLLLLL  8 $ $&&&&&&&&R " " " " " " " "'''''9'''@ggggggggT eE9$%% )S)S))))))sA11B6A==B