U
    c                     @   s2  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 d dlm	Z	m
Z
 d dlZd dlZd dlmZmZ d dlmZ d dlZd dl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m Z  d d	l!m"Z"m#Z# d d
l$m%Z% d dl&m'Z' d dl(m)Z) d dl*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1m2Z2m3Z3 d dl4m5Z5m6Z6 d dl7m8Z8 d dl9m:Z: d dl;m<Z< d dl=m>Z> d dl?m@Z@ d dlAmBZB d dlCmDZDmEZEmFZF dgZGeHeIZJzd dlKZKdZLW n eMk
r   dZKdZLY nX dZNG dd dejOZPdZQeRd d!d"ZSed#d$ ZTd%ZUG d&d' d'e	ZVd(d) ZWeX ejYd*ed+ejZd,d-eU d.de[d/d0ejZd1d2ddeRdd3ej\d4d Z]e]jXd5d6d7d8d9 Z^ej_dddd:Z`d6d;d<Zad=d> Zbd?d@ ZcdAdB ZddCdD Zed7dEdFZfdGdH ZgdIdJ ZhedKdLdMZie^jjdNdOdPejkdQe[dRdSejZdTdUeRddddVejZdWdXeRddddVecejZdYdZele@m dd[ejZd\d]eRddddVejZd^d_eRddddVejZd`daeRddddVejZdbdceRddddVejZdddeendd[ejZdfdendgdhejZdideRddjdkejZdle[dRdmdnejZdodpeRddddVej\dqdr Zoe^jjdsdtdPejkdQe[dRdSejZdudvdeRddddwdxdy Zpe^jjdzd{dPejkdQe[d|dSejZd}d~denddejZdbdceRddddVecej\dd Zqe^jjdddPejkdQe[d|dSejZddddejZd}d~denddejZdddeRddddecej\dd Zre^jXdddPejZddddejZddddejZddddejZddddejZdddddeRddejZdddddeRddejZd}d~denddejZdddddeRddejZdddddeRddejZdddeRddejZdddddeRddejZdddend0ejZdddend0ecejZdeRddddejZddeRdddejZdbdceRddddVejZdodeRddddVej\dd Zsd8ddZtdd Zue2jvdddZwe2jvdddZxe2jydddZzdd Z{dd Z|esjjdddPejkdQe`dSejkde[ddSejZdde`dd[ejZdde`dd[ejZde`dddǍejZdendddʍejZddde[d/dd΍ejZddeRddddVej\dd҄ Z}esjjdddPejkdQe`dSejkde[ddSejkde`dd֍ejZdendddʍejZde`dddǍejZddde[d/dd΍ej\dd܄ Z~ddބ ZejkdQe`dSejkde[ddSejZdde`dd[ejZddendd[ejZddendd[ejZddeRdddejZddendd[ejZdddeddejZdeRddddddejZdendddʍej\dd ZejkdQe`dSejkde[ddSejZdde`dd[ejZdeRddddddejZdddeddej\dd Zdd ZddefddefgZdd Ze  d d Zd9ddZe^jjdddPejkdQe[dRdSejkde[ddSejZddddddd	 Ze]jjd
dd7ejkdQe`dSejkdej_ddddSejkdedSejkdedSejZdddend0ejZdddedddejZdddend0ej\dd Ze]jjddd7ejkdQe`dSejkdej_ddddSejZdfddend0ejZddddej_dddddd Ze]jXddd7d d ZejZd!d"deRddd#Zejjd$d%d7ejkdQe`dSejkdej_ddddSejZdfd&dend0ed'd( Zejjd)dd7ejkdQe`dSejkdej_ddddSejZde`dd*dʍejZdÐd+e`dd[ejZdde[dRdd͐d,ejZddeRddddVed-d. Ze"jd/d0d1Zejjd2dd7ejkdQe`dSejkdej_ddddSejkde`dSejZdde[d/d3d͐d,ed4d5 ZdS (:      N)contextmanager)datetime)Enumauto)cmspem)ValidationContext)__version__)	CLIConfig	LogConfigPemDerSignatureConfigPKCS11PinEntryModePKCS11SignatureConfigPKCS12SignatureConfigStdLogOutputTokenCriteriainit_validation_context_kwargsparse_cli_configparse_logging_config)cryptmisc)ConfigurationError)IncrementalPdfFileWriter)LayoutError)isoparse)PdfFileReader)copy_into_new_writer)fieldssigners
validation)SigningErrorload_certs_from_pemder)DEFAULT_SIGNER_KEY_USAGE)
BuildProps)PdfCMSSignedAttributes)HTTPTimeStamper)RevocationInfoValidationType)SignatureValidationError)QRStampStyleqr_stamp_filetext_stamp_filecliTFZPYHANKO_PKCS11_PINc                   @   s   e Zd ZedddZdS )NoStackTraceFormatterreturnc                 C   s   dS )N  )selfeir0   r0   //tmp/pip-unpacked-wheel-0kb_yl26/pyhanko/cli.pyformatException@   s    z%NoStackTraceFormatter.formatExceptionN)__name__
__module____qualname__strr4   r0   r0   r0   r3   r,   ?   s   r,   z4%(asctime)s - %(name)s - %(levelname)s - %(message)s)verbosec                 C   s   |   D ]\}}t|}||j t|jtrlttjkrJt	t
j}nt	 }|rbtt}qtt}nt|j}tt}|| || qd S N)itemslogging	getLoggersetLevellevel
isinstanceoutputr   STDOUTStreamHandlersysstdout	FormatterLOG_FORMAT_STRINGr,   FileHandlersetFormatter
addHandler)Zlog_configsr9   module
log_configZ
cur_loggerhandler	formatterr0   r0   r3   logging_setupG   s    




rO   c               
   c   sx  d  } }zd V  W n< t jk
r.    Y n$ tjk
r` } z|}d|j } W 5 d }~X Y n tjk
r } z|}d|j } W 5 d }~X Y n tjk
r } z|}d|j } W 5 d }~X Y n tk
r } z|}d|j } W 5 d }~X Y n^ tk
r& } z|}d|j } W 5 d }~X Y n, t	k
rP } z|}d} W 5 d }~X Y nX |d k	rtt
j| |d t | d S )NzcFailed to read PDF file in strict mode; rerun with --no-strict-syntax to try again.
Error message: zFailed to read PDF file: zFailed to write PDF file: z*Error raised while producing signed file: z/Error raised while producing signature layout: zGeneric processing error.exc_info)clickClickExceptionr   ZPdfStrictReadErrormsgZPdfReadErrorZPdfWriteErrorr    r   	Exceptionloggererror)rT   	exceptioner0   r0   r3   pyhanko_exception_manager^   s6    

rZ   zpyhanko.ymlc                   @   sH   e Zd Ze Ze Ze Ze Ze Ze Z	e Z
e Ze Ze ZdS )CtxN)r5   r6   r7   r   SIG_METAEXISTING_ONLYTIMESTAMP_URL
CLI_CONFIGSTAMP_STYLE	STAMP_URLNEW_FIELD_SPEC
PREFER_PSS
DETACH_PEMLENIENTr0   r0   r0   r3   r[      s   r[   c                   C   s   t t jddd d S )NzmWARNING: passphrase is empty. If you intended to sign with an unencrypted private key, use --no-pass instead.T)Zbold)rR   Zechostyler0   r0   r0   r3   _warn_empty_passphrase   s    rg   ZpyHanko)Z	prog_nameversionz--configz.YAML file to load configuration from[default: ]rhelprequiredtypez	--verbosezRun in verbose mode)rl   rm   defaultrn   is_flagc           
   
   C   s  d }|d krz&t td}| }W 5 Q R X t}W q tk
rF   Y q tk
r } ztdt dt| W 5 d }~X Y qX nDz| }W n6 tk
r } ztdt| W 5 d }~X Y nX | t	 |d k	rt
| | jtj< }|j}nti }|r"|d  }ttj|jd|d < n8|d  j}	ttj|	d|d< d|krZttj|	d|d< t|| |rttd |d k	rtd	| d
 n
td d S )Nrj   zFailed to read : zFailed to read configuration: )r?   rA   zpyhanko_certvalidator.fetcherszfontTools.subsetzRunning with --verbosez$Finished reading configuration from .z$There was no configuration to parse.)openDEFAULT_CONFIG_FILEreadFileNotFoundErrorIOErrorrR   rS   r8   Zensure_objectdictr   objr[   r_   rL   r   r   r<   DEBUGrA   WARNINGrO   debug)
ctxconfigr9   Zconfig_textfrY   cfgrL   Zroot_logger_configZ
log_outputr0   r0   r3   r+      sZ    
 
 

 



zsign PDFs and other filessign)rl   namec                   C   s   d S r:   r0   r0   r0   r0   r3   signing   s    r   )existsreadabledir_okayc              
   C   s  | j tjd }z<|d k	rt||fr2td|d krDtdz|j|dd}W nF tk
r }	 z(d| d}
t	j
|
|	d t|
W 5 d }	~	X Y nX n||s|rt||||d}nb|d k	rz|jdd}W n@ tk
r }	 z d	}
t	j
|
|	d t|
W 5 d }	~	X Y nX ni }|d k	r0||d
< n|d
d |rJd|d< |W S  tjk
rh    Y n~ tk
r }	 z d}
t	j
|
|	d t|
W 5 d }	~	X Y n@ tk
r }	 z d}
t	j
|
|	d t|
W 5 d }	~	X Y nX d S )NzC--validation-context is incompatible with --trust and --other-certszNo config file specified.T)Zas_dictzAConfiguration problem. Are you sure that the validation context '0' is properly defined in the configuration file?rP   )trusttrust_replaceother_certsretroactive_revinfoz*Failed to load default validation context.allow_fetchingr   z+I/O problem while reading validation configz:Generic processing problem while reading validation config)ry   getr[   r_   anyrR   rS   Zget_validation_contextr   rV   rW   r   
setdefaultrw   rU   )r}   validation_contextr   r   r   r   r   
cli_configresultrY   rT   r0   r0   r3   _build_vc_kwargs   sf    
 

 


r   c                 C   s(   | j tjd }|d krd S |j|dS )N)r   )ry   r   r[   r_   Zget_signer_key_usages)r}   r   r   r0   r0   r3   _get_key_usage_settings+  s    r   c              	   C   sf   t jdddtd| } t jddddtd| } t jd	d
dtdddd| } t jddddtd| } | S )Nz--validation-contextz"use validation context from configFrk   z--trustz#list trust roots (multiple allowed)T)rl   rm   multiplern   z--trust-replacez4listed trust roots supersede OS-provided trust storerl   rm   rn   rp   ro   show_defaultz--other-certsz#other certs relevant for validation)rR   optionr8   readable_filebool)r   r0   r0   r3   trust_options7  sL               r   c              
   C   s   z| j tj }W n0 tk
r@   |s*Y d S tdt dY nX z||}W nF tk
r } z(d| d}t	j
||d t|W 5 d }~X Y nX |rt|tstdn|st|trtd|S )Nz2Using stamp styles requires a configuration file (z by default).z4Configuration problem. Are you sure that the style 'r   rP   zAThe --stamp-url parameter is only meaningful for QR stamp styles.z/QR stamp styles require the --stamp-url option.)ry   r[   r_   KeyErrorrR   rS   rt   Zget_stamp_styler   rV   rW   r@   r(   )r}   
style_nameurlr   rf   rY   rT   r0   r0   r3   _select_styleM  s0    


r   c                 C   s6   |r|rt d|rd}n|r&d}nd}|| d< | S )Nz<--soft-revocation-check is incompatible with --force-revinforequirez	soft-fail	hard-failrevocation_moderR   rS   )	vc_kwargssoft_revocation_checkforce_revinfoZrev_moder0   r0   r3   _prepare_vcl  s    r   c                 C   sD   | d kr*t f |}tjjj||||d}ntj|| ||||d}|S )N)key_usage_settingssigner_validation_context	skip_diff)r   r   Zvalidation_context_kwargsr   )r   pyhankor   r   Zvalidate_pdf_signatureZvalidate_pdf_ltv_signature)ltv_profiler   r   r   embedded_sigr   vcstatusr0   r0   r3   _signature_status}  s"    
  r   c           	   
   C   s   |  }zBt|r$t|\}}}tj|}|d jdkrHt	dW n. t
k
rx } zt	d|W 5 d }~X Y nX tj| |d ||d}t|S )Ncontent_typesigned_dataz"CMS content type is not signedDatazCould not parse CMS objectcontent)r   r   r   )ru   r   detectZunarmorr   ZContentInfoloadZnativerR   rS   
ValueErrorr   Zasync_validate_detached_cmsasynciorun)	infileZ
sig_infiler   r   Z	sig_bytes_Zcontent_inforY   Zvalidation_coror0   r0   r3   _validate_detached  s     
 r   c              
   C   s  zL|  }|r&|s&|j rdnd|j fW S |r:| |j fW S | |j fW S W n tjk
r } z8dt| }t| |r|df W Y S W Y dS W 5 d }~X Y n\ tk
 r } z<dt| }tj||d |r|df W Y S W Y dS W 5 d }~X Y nX d S )	NZVALIDINVALIDzOAn error occurred while parsing the revocation information for this signature: F)ZREVINFO_FAILUREFz3An error occurred while validating this signature: rP   )r   F)	Zbottom_lineZpretty_print_detailssummaryr   ZValidationInfoReadingErrorr8   rV   rW   r'   )status_callbackpretty_printexecutive_summaryr   rY   rT   r0   r0   r3   _signature_status_str  s,    
r   r-   c                 C   s8   zt | }W n& tk
r2   td| dY nX |S )Nz	datetime z could not be parsed)r   r   rR   rS   )Zdt_strdtr0   r0   r3   _attempt_iso_dt_parse  s
    r   validatezvalidate signaturesr   rl   r   rb)rn   z--executive-summaryz/only print final judgment on signature validity)rl   rn   rp   ro   r   z--pretty-printz8render a prettier summary for the signatures in the filez--ltv-profilez LTV signature validation profile)rl   rn   rm   z--force-revinfozJFail trust validation if a certificate has no known CRL or OCSP endpoints.z--soft-revocation-checkzbDo not fail validation on revocation checking failures (only applied to on-line revocation checks)z--no-revocation-checkzJDo not attempt to check revocation status (meaningless for LTV validation)z--retroactive-revinfozOTreat revocation info as retroactively valid (i.e. ignore thisUpdate timestamp)z--validation-timezOverride the validation time (ISO 8601 date). The special value 'claimed' causes the validation time claimed by the signer to be used. Revocation checking will be disabled. Option ignored in LTV mode.z
--passwordz9password to access the file (can also be read from stdin))rm   rn   rl   z--no-diff-analysisz#disable incremental update analysis)ro   rn   rp   rl   z
--detachedziRead signature CMS object from the indicated file; this can be used to verify signatures on non-PDF files)rn   rl   z--no-strict-syntaxzAttempt to ignore syntactical problems in the input file and enable signature validation in hybrid-reference files.(warning: this may affect validation results in unexpected ways.)c              	      sj  ||d k	O }|rd}
|r&|r&t dd k	rH|d k	r@t dtt| ||||||r^dnd dd}|dkrxd}n|d k	rt|d< t| |t|
dt   d k	rt fd	d
||d\}}|rt	| n
t |W 5 Q R  d S |rt
d tdd}nt}|j}t|tjrr|d krLtjdd}||}|jtjjkrt dn|d k	rt dd}t|jD ]\}jj }|rjd< tfdd
||d\}}j}|r.d|d  d| }dt| }t	| t	| t	| t	d|  nt	d|||f  ||M }q|s\t dW 5 Q R X d S )NTz8--pretty-print is incompatible with --executive-summary.z6--validation-time is not compatible with --ltv-profileFr   ZclaimedZmoment)r   r   c                      s   t  tf S r:   )r   r   r0   )detachedr   r   r   r0   r3   <lambda>-  s
     z%validate_signatures.<locals>.<lambda>)r   r   r   zQStrict PDF syntax is disabled; this could impact validation results. Use caution.strictFile password: promptPassword didn't match.zIThe CLI supports only password-based encryption when validating (for now)c                      s   t  dS )N)r   r   r   r   r   r   )r   r0   )r   r   r   r   no_diff_analysisr   r0   r3   r   T  s      zField    rq   =z

z%s:%s:%szValidation failed)rR   rS   r&   r   r   r   r   rZ   r   printrV   infor   security_handlerr@   r   StandardSecurityHandlergetpassdecryptr   
AuthStatusFAILED	enumerateembedded_regular_signaturessigner_certsha256hexZself_reported_timestamp
field_namelen)r}   r   r   r   r   r   r   r   r   r   r   Zno_revocation_checkpasswordr   r   r   Zvalidation_timeno_strict_syntaxZuse_claimed_validation_timeZ
status_strZsignature_okrj   shauth_resultZall_signatures_okixfingerprintr   headerliner0   )r   r   r   r   r   r   r   r   r3   validate_signatures  s    >    

 
 






 
r   listzlist signature fieldsz--skip-statuszdo not print statusr   c              	   C   sl   t  \ t| }t|}t|D ]:\}\}}}|r>t| q"t| d|d krRdnd  q"W 5 Q R X d S )N:ZEMPTYZFILLED)rZ   r   r   Zenumerate_sig_fieldsr   r   )r   Zskip_statusrj   Z
field_infor   r   valueZ	field_refr0   r0   r3   list_sigfieldsl  s    
r   Z	ltaupdatezupdate LTA timestampzr+bz--timestamp-urlzURL for timestamp server)rl   rm   rn   ro   c              	   C   sP   t  @ t| |||||}t|}	t|}
t|	|
tf | W 5 Q R X d S r:   )rZ   r   r%   r   r   PdfTimeStamperZupdate_archival_timestamp_chainr   )r}   r   r   r   r   r   timestamp_urlr   r   timestamperrj   r0   r0   r3   
lta_update|  s        
 r   Zltvfixz5add revocation information for a signature to the DSSz--fieldzname of the signature field)rl   rm   z--apply-lta-timestampz8Apply a document timestamp after adding revocation info.)rl   rm   rn   ro   rp   r   c	              	      s   |r|st dt| ||||ddd}	d|	d< t|}
zt fdd|
jD }W n& tk
rz   t d	  d
Y nX tj|t	f |	dd}|rt
|}t|jt|tjt	f |	dd d S )Nz8Please specify a timestamp server using --timestamp-url.FT)r   r   r   r   c                 3   s   | ]}|j  kr|V  qd S r:   )r   ).0sfieldr0   r3   	<genexpr>  s    
 zltv_fix.<locals>.<genexpr>z(Could not find a PDF signature labelled rr   )Zin_place)rR   rS   r   r   nextr   StopIterationr   Zadd_validation_infor   r%   r   r   Ztimestamp_pdfr   
DEFAULT_MD)r}   r   r   r   Zapply_lta_timestampr   r   r   r   r   rj   Zemb_sigrA   r   r0   r   r3   ltv_fix  sH         

  
  r   addsigzadd a signaturez--namezexplicitly specify signer namez--reasonzreason for signingz
--locationzlocation of signingz	--certifyzadd certification signature)rl   rm   ro   rp   rn   r   z--existing-onlyznever create signature fieldsz--use-padesz)sign PAdES-style [level B/B-T/B-LT/B-LTA]z--use-pades-ltazproduce PAdES-B-LTA signaturez--prefer-pssz6prefer RSASSA-PSS to PKCS#1 v1.5 padding, if available)rp   ro   rn   rl   z--with-validation-infozembed revocation infoz--style-namez)stamp style name for signature appearancez--stamp-urlz$QR code URL to use in QR stamp stylez--detachz^write only the signature CMS object to the output file; this can be used to sign non-PDF files)rn   rp   ro   rl   z--detach-pemz2output PEM data instead of DER when using --detach)rl   rn   rp   ro   zAttempt to ignore syntactical problems in the input file and enable signature creation in hybrid-reference files.(warning: such documents may behave in unexpected ways)c                 C   sH  |p
|d k| j tj< || j tj< || j tj< |rL|| j tj< d | j tj< d S |	rfd }}
|sftd|rtt	j
j}nt	j
j}t}|
rt| |||||dd}tf |}t| |}|d k	r|jd k	r|j}nd }t|dd\}}tj|||||||
|||	tdtdd| j tj< || j tj< t| ||| j tj< || j tj< || j tj< d S )	NTz/--timestamp-url is required for --use-pades-ltar   F)require_full_speczpyHanko CLI)r   revision)r   locationreasonr   certify	subfilterZembed_validation_infor   Zsigner_key_usageuse_pades_ltaZapp_build_props)ry   r[   r]   r^   rc   rd   r\   rR   rS   r   ZSigSeedSubFilterZPADESZADOBE_PKCS7_DETACHEDr"   r   r   r   	key_usageparse_field_location_specr   ZPdfSignatureMetadatar#   r	   rb   r   r`   ra   re   )r}   r   r   r   r   r  Zexisting_onlyr   Z	use_padesr  Zwith_validation_infor   r   r   r   r   	stamp_url
prefer_pssr   detachZ
detach_pemr   r  r  r   r   Zkey_usage_settr   new_field_specr0   r0   r3   r     sp    :
     

 
     c           	      C   s   t | d}t|| d}|jjr|jj}t|tjrPtjd|  d}|	| nDt|tj
r|d k	rt||}td|   || n
td|S )Nr   r   z"Password for encrypted file '%s': r   a  The file '%s' appears to be encrypted using public-key encryption. This is only partially supported in pyHanko's CLI. PyHanko will attempt to decrypt the document using the signer's public key, but be aware that using the same key for both signing and decryption is considered bad practice. Never use the same RSA key that you use to decrypt messages tosign hashes that you didn't compute yourself!zRInput file appears to be encrypted, but appropriate credentials are not available.)rs   r   prevZ	encryptedr   r@   r   r   r   encryptPubKeySecurityHandlerSimpleEnvelopeKeyDecrypterrV   warningencrypt_pubkeyrR   rS   )	infile_pathlenientr   
signer_keyr   writerr   Zpdf_passcredr0   r0   r3   _open_for_signing4  s.    
	r  c                 C   s$   d }| j tj }|d k	r d|i}|S )Nr   )ry   r[   ra   )r}   text_paramsr  r0   r0   r3   get_text_paramsW  s
    r  )signerc                 C   s   t | ||||}t|S r:   )async_detached_sigr   r   )r  r  outfiler   use_pemcoror0   r0   r3   detached_sig_  s        r  c           
   
      s   t   |d k	rt|}d }nd }tjt d}t|d&}| j|tj	|t
|ddI d H }W 5 Q R X | }	|rtd|	}	||	 W 5 Q R X d S )N)tzr   )Zsigning_time)r   Zsigned_attr_settingsZPKCS7)rZ   r%   r   nowtzlocalZget_localzoners   Zasync_sign_general_datar   r   r$   dumpr   Zarmorwrite)
r  r  r  r   r  r   	timestampinf	signatureZoutput_bytesr0   r0   r3   r  g  s&      r  c
                 C   sZ   t  J |d k	rt|}
nd }
t|| j| j|	d}t|||| |
||||d	 W 5 Q R X d S )N)r   r  r  	r  r  signature_metar  r   rf   r	  existing_fields_onlyr  )rZ   r%   r  Zsigning_certZsigning_keygeneric_sign_pdf)r  r  r  r   r'  r(  rf   r  r	  r  r   r  r0   r0   r3   addsig_simple_signer  s*    
       r*  c        	         C   sR   t j|||||dj| ||d}	|	 }
||
 |
  | jj  |  d S )N)r  r   stamp_styler	  )r(  Zappearance_text_params)	r   Z	PdfSignerZsign_pdf	getbufferr"  releaser
  streamclose)r  r  r'  r  r   rf   r	  r(  r  r   bufr0   r0   r3   r)    s         
r)  c              
   C   s`   | d krd S zt t| W S  ttfk
rZ } ztjd|  |d W Y d S d }~X Y nX d S )Nz!Could not load certificates from rP   )r   r!   rw   r   rV   rW   )filesrY   r0   r0   r3   
grab_certs  s    r2  Zpemderz$read key material from PEM/DER filesr  wbz--keyz)file containing the private key (PEM/DER)z--certz2file containing the signer's certificate (PEM/DER)z--chainzkfile(s) containing the chain of trust for the signer's certificate (PEM/DER). May be passed multiple times.)rn   r   rl   z--pemder-setupzCname of preconfigured PEM/DER profile (overrides all other options))rn   rm   rl   z
--passfilez2file containing the passphrase for the private keystdin)rl   rm   rn   r   z	--no-passz*assume the private key file is unencryptedc	                 C   s  | j tj }	| j tj }
| j tj }|r| j tjd }|d krJtdz|	|}W q t
k
r } z&d| }tj||d t|W 5 d }~X Y qX n0|r|stdnt||t|| j tj d}|jd k	r|j}nX|d k	r|  d}|  n2|jr6|s6tjddd}|s:t  nd }|j|d	}| j tj d krrt||||| j tj d
 t|||||	|
| j tj t| | j tj | j tjdd
 d S )Nz7The --pemder-setup option requires a configuration filez"Error while reading PEM/DER setup rP   zXEither both the --key and --cert options, or the --pemder-setup option must be provided.)key_file	cert_filer   r  utf-8Key passphrase: r   )Zprovided_key_passphraser   r  Fr   r'  r(  rf   r  r	  r  ) ry   r[   r\   r]   r^   r   r_   rR   rS   Zget_pemder_configr   rV   rW   r   r2  rc   key_passphrasereadlinestripencoder/  prompt_passphraser   rg   instantiater  rd   r*  r`   r  rb   re   )r}   r   r  keycertchainZpemder_setuppassfileno_passr'  r(  r   r   Zpemder_configrY   rT   
passphraser  r0   r0   r3   addsig_pemder  sp    
  



   
   
 
rG  Zpkcs12z%read key material from a PKCS#12 filepfx)rn   rm   z--p12-setupzCname of preconfigured PKCS#12 profile (overrides all other options)zPEM/DER file(s) containing extra certificates to embed (e.g. chain of trust not embedded in the PKCS#12 file)May be passed multiple times.z4file containing the passphrase for the PKCS#12 file.c                 C   s  | j tj }| j tj }| j tj }	|r| j tjd }
|
d krJtdz|
	|}W q t
k
r } z&d| }tj||d t|W 5 d }~X Y qX n*|stdnt|t|| j tj d}|jd k	r|j}nF|d k	r|  d}|  n |jrtjddd}nd }|j|d	}| j tj d krZt||||	| j tj d
 t||||	||| j tj t| | j tj | j tjdd
 d S )Nz4The --p12-setup option requires a configuration filez#Error while reading PKCS#12 config rP   zCEither the PFX argument or the --p12-setup option must be provided.)Zpfx_filer   r  r7  zPKCS#12 passphrase: r   )Zprovided_pfx_passphraser9  Fr:  )ry   r[   r\   r]   r^   r   r_   rR   rS   Zget_pkcs12_configr   rV   rW   r   r2  rc   Zpfx_passphraser<  r=  r>  r/  r?  r   r@  r  rd   r*  r`   r  rb   re   )r}   r   r  rH  rC  rD  Z	p12_setupr'  r(  r   r   Zpkcs12_configrY   rT   rF  r  r0   r0   r3   addsig_pkcs12  sn    
 



   
   
 
rI  c                 C   s   t   | jtj d kr>t||||| jtj dW  5 Q R  S |d k	rPt|}nd }tt|| j	tj
d|| jtj ||| jtj | jtj | jtj t| d	 W 5 Q R X d S )Nr9  Fr&  )rZ   ry   r[   r\   r  rd   r%   r)  r  r   re   r`   rb   r]   r  )r}   r  r   r  r   r   r0   r0   r3   _sign_pkcs11N  s.       


  


rJ  z--libzpath to PKCS#11 modulez--token-labelzPKCS#11 token labelz--cert-labelzcertificate labelz--raw-mechanismzinvoke raw PKCS#11 mechanism)rl   rn   rp   rm   z--key-labelz	key labelz	--slot-nozspecify PKCS#11 slot to usez--skip-user-pinz7do not prompt for PIN (e.g. if the token has a PIN pad))rn   r   ro   rm   rp   rl   z--p11-setupzCname of preconfigured PKCS#11 profile (overrides all other options)c              
   C   s  ddl m} | jtj }|	r| jtjd }|d kr>tdz|	|	}W q t
k
r } z&d|	 }tj||d t|W 5 d }~X Y qX n<|r|std|rtjntj}t||||t|||
d}|j}|d krtjtd }|r| }|jtjkr|d krtjdd	}z.|j||d
}t| |||| W 5 Q R X W nP |jk
r } z.tjd|d tdt|j d| W 5 d }~X Y nX d S )Nr   )pkcs11z4The --p11-setup option requires a configuration filez#Error while reading PKCS#11 config rP   z3The parameters --lib and --cert-label are required.)module_path
cert_label	key_labelslot_noZtoken_criteria
prompt_pinraw_mechanismzPKCS#11 user PIN: r   )user_pinPKCS#11 errorPKCS#11 error: [] )pyhanko.signrK  ry   r[   r^   r   r_   rR   rS   Zget_pkcs11_configr   rV   rW   r   ZSKIPZPROMPTr   r   rR  osenvironP11_PIN_ENV_VARr=  rP  r   ZPKCS11SigningContextrJ  PKCS11Errorrn   r5   )r}   r   r  libZtoken_labelrM  rN  rO  Zskip_user_pinZ	p11_setuprQ  rK  r   r   Zpkcs11_configrY   rT   Zpinentry_modeZpinZpin_envr  r0   r0   r3   addsig_pkcs11f  sZ    

   r\  z"path to libbeidpkcs11 library filez--use-auth-certzuse Authentication cert insteadc              
   C   s   ddl m} |sB| jtjd }|d ks2|jd kr<td|j}| jtj	 }z|j
||d}	W nN tjk
r }
 z.tjd|
d tdt|
j d|
 W 5 d }
~
X Y nX |	$ |j|	|d	}t| |||| W 5 Q R X d S )
Nr   )beidz\The --lib option is mandatory unless beid-module-path is provided in the configuration file.)rO  rS  rP   rT  rU  )use_auth_cert)rV  r]  ry   r   r[   r_   Zbeid_module_pathrR   rS   r^   Zopen_beid_sessionrK  rZ  rV   rW   rn   r5   Z
BEIDSignerrJ  )r}   r   r  r[  r^  rO  r]  r   r   sessionrY   r  r0   r0   r3   addsig_beid  s"    .r`  c                 C   s   t j| |d| d S )Nr   )r   command)r   hlpfunr0   r0   r3   _pkcs11_cmd  s    rd  rK  z"use generic PKCS#11 device to signr]  zuse Belgian eID to signc                  C   sD   t rtD ]} t|   qn(dd }tD ]\}}}t||d | q$d S )Nc                   S   s   t dd S )Nz7This subcommand requires python-pkcs11 to be installed.r   r0   r0   r0   r3   _unavailable  s    z._process_pkcs11_commands.<locals>._unavailablez [dependencies missing])pkcs11_availablePKCS11_COMMANDSrd  )argsre  r   rb  rc  r0   r0   r3   _process_pkcs11_commands  s    ri  c                 C   sT   z,t | }|st|dkr$|d W S |W S W n" tk
rN   td|  Y nX d S )Nr   r   z=Sig field parameter PAGE should be a nonzero integer, not %s.)intr   rR   rS   )pagepage_ixr0   r0   r3   _index_page  s    

rm  c           
      C   s   | d kr|rt ddS z| d\}}}W n0 tk
r^   |rNt dn| d f Y S Y nX t|}ztt|d\}}}}	W n tk
r   t dY nX |tj||||||	fdfS )Nz(A signature field spec was not provided.)NN/z;Sig field spec should be of the form PAGE/X1,Y1,X2,Y2/NAME.,z9Sig field parameters X1,Y1,X2,Y2 should be four integers.)Zsig_field_nameZon_pagebox)	rR   rS   splitr   rm  maprj  r   ZSigFieldSpec)
specr   rk  rp  r   rl  x1y1Zx2y2r0   r0   r3   r    s4    
  
r  Z	addfieldsz)add empty signature fields to a PDF fieldzPAGE/X1,Y1,X2,Y2/NAME)metavarr   rm   c              	   C   sf   t  V t| }|D ](}t|\}}|d k	s0tt|| q|| |   |  W 5 Q R X d S r:   )rZ   r   r  AssertionErrorr   Zappend_signature_fieldr"  r/  )r   r  r   r  r   r   rs  r0   r0   r3   add_sig_field$  s    
ry  zstamp PDF filesstamp)writabler   xyz%stamp style name for stamp appearancez--pagez)page on which the stamp should be appliedr   )rl   rm   rn   ro   r   c           
   
   C   sZ   t  J t| ||}t|}	|r8t||||	|||d nt||||	||d W 5 Q R X d S )N)	dest_pager|  r}  r   )r~  r|  r}  )rZ   r   rm  r)   r*   )
r}   r   r  r|  r}  r   rk  r  r+  rl  r0   r0   r3   rz  ;  s*              z encrypt PDF files (AES-256 only)r  z!password to encrypt the file withz--recipientzIcertificate(s) corresponding to entities that can decrypt the output file)r   r   )rm   r   rl   rn   c           	      C   s   |r|rt dn|s(|s(tjdd}d }|r>tt|d}t h t| dR}t|}t|}|rr|	| n|j
|d t|d}|| W 5 Q R X W 5 Q R X W 5 Q R X d S )Nz2Specify either a password or a list of recipients.zOutput file password: r   )Z
cert_filesr   )Z
owner_passr3  )rR   rS   r   r   r!   rZ   rs   r   r   r  r  r"  )	r   r  r   Z	recipientZrecipient_certsr$  rj   woutfr0   r0   r3   encrypt_file\  s(    r  z6decrypt PDF files (any standard PDF encryption scheme)r   c                   C   s   d S r:   r0   r0   r0   r0   r3   r     s    z--forcez1ignore access restrictions (use at your own risk))rl   rm   rn   rp   ro   zdecrypt using passwordr   z!password to decrypt the file withc           	      C   s   t   t| d}t|}|jd kr0td|s@tjdd}||}|jt	j
jkrh|shtdn|jt	j
jkrtdt|}t|d}|| W 5 Q R X W 5 Q R X W 5 Q R X d S )Nr   File is not encrypted.r   r   zjPassword specified was the user password, not the owner password. Pass --force to decrypt the file anyway.r   r3  )rZ   rs   r   r   rR   rS   r   r   r   r   r   USERr   r   r"  )	r   r  r   forcer$  rj   r   r  r  r0   r0   r3   decrypt_with_password  s"    	



r  z#decrypt using private key (PEM/DER)z5file containing the recipient's private key (PEM/DER)z5file containing the recipient's certificate (PEM/DER))rm   rn   rl   r   c           	      C   sd   |d k	r|  }|  n&|s<tjddd}|s@t  nd }tjj|||d}t|| || d S )Nr8  r   r7  )r;  )	ru   r/  r   r>  rg   r   r  r   _decrypt_pubkey)	r   r  rA  rB  rD  r  rE  rF  sedkr0   r0   r3   decrypt_with_pemder  s    
  r  )r  c           	      C   s   t   t|d}t|}|jd kr0tdt|jtjsHtd|	| }|j
tjjkrp|stdn|j
tjjkrtdt|}t|d}|| W 5 Q R X W 5 Q R X W 5 Q R X d S )Nr   r  z:File was not encrypted with a public-key security handler.zhChange of encryption is typically not allowed with user access. Pass --force to decrypt the file anyway.zFailed to decrypt the file.r3  )rZ   rs   r   r   rR   rS   r@   r   r  Zdecrypt_pubkeyr   r   r  r   r   r"  )	r  r   r  r  r$  rj   r   r  r  r0   r0   r3   r    s(    



r  z#decrypt using private key (PKCS#12)z3file containing the passphrase for the PKCS#12 filec                 C   sX   |d krt j ddd}n|  d}|  tjj||d}t|| || d S )Nr8  r   r7  )rF  )	r   r>  r<  r=  r/  r   r  Zload_pkcs12r  )r   r  rH  rD  r  rF  r  r0   r0   r3   decrypt_with_pkcs12  s    	 r  )N)F)NN)T)r   r   r<   rW  rD   
contextlibr   r   enumr   r   rR   r   Z
asn1cryptor   r   Zpyhanko_certvalidatorr   Z$pyhanko.sign.validation.pdf_embeddedr   r	   Zpyhanko.configr
   r   r   r   r   r   r   r   r   r   r   Zpyhanko.pdf_utilsr   r   Zpyhanko.pdf_utils.config_utilsr   Z$pyhanko.pdf_utils.incremental_writerr   Zpyhanko.pdf_utils.layoutr   Zpyhanko.pdf_utils.miscr   Zpyhanko.pdf_utils.readerr   Zpyhanko.pdf_utils.writerr   rV  r   r   r   Zpyhanko.sign.generalr    r!   Zpyhanko.sign.signersr"   Z"pyhanko.sign.signers.pdf_byteranger#   Zpyhanko.sign.signers.pdf_cmsr$   Zpyhanko.sign.timestampsr%   Zpyhanko.sign.validationr&   Zpyhanko.sign.validation.errorsr'   Zpyhanko.stampr(   r)   r*   __all__r=   r5   rV   rK  rf  ImportErrorrY  rF   r,   rG   r   rO   rZ   rt   r[   rg   groupZversion_optionr   ZFileZpass_contextr+   r   Pathr   r   r   r   r   r   r   r   r   r   ra  argumentZChoiceas_tupler8   r   r   r   r   r   r  r  ZSignerr  r  ZSimpleSignerr*  r)  r2  rG  rI  rJ  rj  r\  r`  rd  rg  ri  rm  r  ry  rz  r  r   Zdecrypt_force_flagr  r  r  r  r  r0   r0   r0   r3   <module>   s  4


"	
 
  ;

D
	                   
    (k
             #
                                 09#
  

    9

: 

    
  
; 
                        

    