U
    I(iA                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl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lmZ d d	lT d
dlmZ ddlmZ ddlmZ d
dlmZ G dd dejZdS )    N)pbkdf2_hmac)AES)SHA256)RSA)get_random_bytes)
PKCS1_v1_5)pad)*   )
send_email   )auth)LdapStatusCode)
Supervisorc                	       s:  e Zd ZdZdZejeej	
ejdddgejdZedd Zed	d
 Zdd Zedd ZdfddZedd ZdgddZdd ZdhddZeedddZdiedd d!Zedjd"d#Z ed$d% Z!ed&d' Z"ed(d) Z#ed*d+ Z$d,d- Z%d.d/ Z&d0d1 Z'd2d3 Z(d4d5 Z)ed6d7 Z*ed8d9 Z+ed:d; Z,d<d= Z-dkd>d?Z.dld@dAZ/edBdC Z0edDdE Z1dmdGdHZ2dne3e4e4e4edIdJdKZ5edLdM Z6edodNdOZ7 fdPdQZ8dRdS Z9edTdU Z:ee;dVdWdXZ<edYdZ Z=ed[d\ Z>ed]d^ Z?edpd_d`Z@eeAddaddbdcddde ZB  ZCS )qCmfAuth    
   modulesr   Z	templates)loaderZ
autoescapec                 C   s   t | jdd S )N$base64	b64decode	pass_hashsplitself r   ./modules/auth/models/auth.pykey&   s    zCmfAuth.keyc                 C   s   t | jdd S )Nr   r   r   r   r   r   salt*   s    zCmfAuth.saltc                 C   s2   t | j}|ttt 7 }|| j 7 }|S N)secrets	token_hextoken_lengthstrinttimer"   hex)r   server_challenger   r   r   gen_server_challenge.   s    zCmfAuth.gen_server_challengec                 C   s   d| j d  }}||| }||d  }}||| }|t| }}t||| }td| |d}	t| j }
||
 | | }t	t
j}t
|	t
j|}|t| t
j}||  S )Nr   r   r   sha256順 )r&   lenbytesfromhexhashlibr   encoder$   r%   r   r   Z
block_sizenewZMODE_CBCZencryptr   r*   )clsloginpasswordr+   startendZserver_randomZserver_timestampZserver_saltZtest_keyZclient_randomsecretZivZcipherZencrypted_secretr   r   r   test_gen_server_challenge_resp4   s$       
z&CmfAuth.test_gen_server_challenge_resprestore_passwordFc                 C   sv   | j dd t| jd}|dkr*| j|d< |rPtdd d| d	tj| S tdd d
| d	tj| S dS )u   
        Сформируем ссылку на сброс и отправим её пользователю.
        Альтернативно переиспользуется для приглашения нового пользователя.
        F)reset)hr<   r6   T)absolutezservicedesk/auth/?zauth/N)reset_pass_set_datadictreset_password_hashr6   auth_base_hrefurllibparse	urlencode)r   ZendpointZsdeskparamsr   r   r   reset_pass_linkO   s    
"zCmfAuth.reset_pass_linkc              	   C   s2  t jj|dddgd}|sRt " t jjddd |ddd	d
 W 5 Q R X td|jr|jt		 kr|jd t		 d krt " t jjddd |ddd	d
 W 5 Q R X t
ddtj }| }| jd}|j|td}t j }|j|jj||d t   t jjddd d|idd
 W 5 Q R X d S )Nreset_password_expiresr6   emailr6   fieldsZrestore_password_get_linkr   zLogin not foundr6   reasonfail)operatecmf_model_nameparent
audit_dataresult_statusu,   Такого пользователя нетQ i,  zAlready sentu   Вам на почту уже отправлена ссылка для сброса пароля. Для повторной отправки повторите попытку позже.uC   Ссылка для восстановления доступа к zreset_password_email.html)Zrestore_linkconfig)subjectok)modelsr   getcmfutildisable_aclCmfAuditaudit_eventZCmfAuthErrorrJ   r)   ZCmfErrorrW   HOSTNAME_FQDNrI   
_jinja_envZget_templateZrenderZCmfPluginMailBoxZget_local_mailboxZsend_messagerK   value)r5   r6   r   rX   linktemplatemessageZmail_boxr   r   r   send_pass_link^   sB    

 

 


 zCmfAuth.send_pass_linkTc                 C   s:   |rdnt d| _|rdntt d | _|   dS )u  
        Выставляем (или сбрасываем) секретик для сброса пароля
        Не очень хорошо, наверное хранить его в чистом виде, если упрут базу account будет печально,
        т.к. по сути даст доступ ко всем, кто в течение часа до угона БД запросил восстановление пароля.
        По хорошему хэшировать чем-то, что хранится отдельно от БД и периодически менять.
        Но это TODO-преTODO, т.к. паранойя.
        12 байт рандома дают нам 2**(8*12)=79,2E+27 значений. Перебирать по 1 в сек по сети - 2,5E+21 лет.
        :param reset - если True, выставляем всё в None, если False - генерируем новые значения
        N   rV   )r$   Ztoken_urlsaferC   r(   r)   rJ   save)r   r=   r   r   r   rA      s    
zCmfAuth.reset_pass_set_datac                 C   s   | j  pt | j kS )u_    Проверяем что ссылка для сброса пароля не протухла )rJ   r)   r   r   r   r   reset_pass_is_expired   s    zCmfAuth.reset_pass_is_expiredNc                 C   st   ddd}|d kr6| j jtt d|  | jjd}tt|	 
 }tt|	 
 }| d| S )NZRS256ZJWT)ZalgtyprV   )r6   expscope.)r6   rb   r(   r)   rl   r   	b64encodejsondumpsr3   decode)r   dayspayloadheaderr   r   r   
create_jwt   s    
zCmfAuth.create_jwt)jwtc                 C   sF   t t| d   }t t| d   }| d| S )Nrt   rs   rm   )r   rn   ro   rp   r3   rq   )rv   rt   rs   r   r   r   
jwt_to_str   s    zCmfAuth.jwt_to_strc                 C   s^   |d kr|  |}ttj}t }||  ||}t	
| }| d| }|S )Nrm   )ru   r   r4   APPZrsa_private_keyr   updater3   signr   rn   rq   )r   rr   rv   Zsignerdigestrz   resr   r   r   rsa_sign_pack_jwt   s    

zCmfAuth.rsa_sign_pack_jwtc           	      C   s   |  d\}}}t }| d| }||  t|}ttj	}|
||}|s^d S t| }t| }t|}t|}|rtt t|d krtdt |d  d S ||dS )Nrm   rk   u9   Время жизни токена закончилосьrt   rs   )r   r   r4   ry   r3   r   r   r   rx   rsa_public_keyverifyrq   ro   loadsr(   r)   gdebug)	rjwtZ	check_exprt   rs   	signaturer{   rv   verifierZverifiedr   r   r   rsa_verify_unpack_jwt   s"    


zCmfAuth.rsa_verify_unpack_jwtc                 C   sJ   |  d\}}}t| }t| }t|}t|}||dS )Nrm   r~   )r   r   r   rq   ro   r   )r   rt   rs   r   r   r   r   rsa_unpack_jwt   s    

zCmfAuth.rsa_unpack_jwtc              
   C   s   |  d\}}}t }| d| }||  t|}d}z$t|}t	|}	|	
||}W n@ tk
r }
 z"d|
 }t| t||
W 5 d }
~
X Y nX |S )Nrm   Fu,   Не удалось разобрать JWT: )r   r   r4   ry   r3   r   r   r   Z
import_keyr   r   
ValueErrorloggingerror)r   Zrsa_public_key_bytesrt   rs   r   r{   rv   r|   r   r   er   r   r   r   rsa_verify_jwt   s    




zCmfAuth.rsa_verify_jwtc              
   C   s|  t d |st d d S z| |}W n2 tk
r\ } ztjd d }W 5 d }~X Y nX |spt d d S | dd}|d d |_|d d |_|d d	 |_	d |_
d |_d }tjtd
 rttd
 }|  }W 5 Q R X | |_|j	pddD ]T}|r|| dr"d|_|dkr t jjr t d|  d|_
d|_q t d|j d|j	 d|j  |S )Nzfrom_jwt: startzfrom_jwt: warn not jwtzfail unpack jwtz2from_jwt: warn not cls.rsa_verify_unpack_jwt(rjwt)T)emptyrs   r6   rl   z/custom/org_name  :r	   uC   from_jwt: Доступ по билету тех поддержки zfrom_jwt: jwt is ok, z, z, is_local=)r   r   r   	Exceptionrx   logger	exceptionr6   rK   rl   Zjwt_is_supportZjwt_is_match_orgospathexistsPROJECT_DIRopenreadstripr   
startswithglobal_settingsZsupport_mode)r5   r   rv   r   objorg_namefZpermr   r   r   from_jwt   s@    




"zCmfAuth.from_jwtc           
      C   s  | j dd|gdgd}|s0| j dd|gdgd}|sJ| j dd|gdgd}|stjj & tjjddd d|id	d
||d W 5 Q R X d S |jrt	
d|j d tjj . tjjddd |jddd	d
|j|jd W 5 Q R X tdt	jj d d S |jj dr|jd\}}tjj|drtjj|dgdD ]}z||jj|}W n: tk
r } zt	
d| d|  W 5 d }~X Y nX |tjkr q\n|tjkrtd  q\n|tjkr>| r d S d|_|  d|  }	t j!"|	d tjj 4 tjjddd |jjddd d
|jj|jjd W 5 Q R X |  S q>tjj 4 tjjddd |jjddd	d
|jj|jjd W 5 Q R X |j#r||jj d!r|| rd S | $||j#jrBd"|_|  d|  }	t j!"|	d tjj ( tjjddd |d"dd d
||d W 5 Q R X |S tjj ( tjjddd |d"dd	d
||d W 5 Q R X |%  d|  }	t j!"|	d
 d S )#N	ext_loginZILIKEz***)filterrM   r6   rK   Zident_failedr   rP   r
   rQ   rR   rS   rT   rU   security_levelparent_nameparent_codeus   Превышено количество попыток ввода пароля для учетной записи "u$   ", вход заблокированauth_failedzToo many failed login attemptsrN   un   Превышено количество попыток ввода пароля, повторите через u    минутZ
allow_ldap@)domainplugin.*)r   rM   u/   Ошибка авторизации через z: u6   Учетная запись заблокированаZldapzauth:user_last_login_fail:r   auth_successed)r6   typerY   Z
allow_basebase)&r[   cmfutilr\   r]   rZ   r^   r_   fail_block_end_dater   r   r6   	cmf_alertr   auth_fail_timeoutauth_optionsrb   r   CmfAuthLdapPlugincountlistZsigninr   r   r   ZINVALID_CREDENTIALSZUSER_DISABLEDSUCCESS_is_permanent_blocklast_auth_typeauth_success_hooklowerrx   REDIS_DBsetr   check_secretauth_fail_hook)
r5   r6   Zchallenge_respr   _r   auth_pluginZldap_status_coder   db_keyr   r   r   get_by_challenge_resp  s    
   
(

   
   

   
   zCmfAuth.get_by_challenge_respc                 C   sr   t jjrn| jrnt d| j d tjj	 . t
jjddd | jdddd| j| jd	 W 5 Q R X td
 dS dS )Nu   Учетная запись "u3   " перманентно заблокированаr   r   zPermanent blockrN   rP   r
   r   ul   Учетная запись заблокирована, обратитесь к администраторуTF)r   r   auth_fail_permanent_blockfail_permanent_blockr   r6   r   r   r\   r]   rZ   r^   r_   r   r   r   r   r   r   w  s     
zCmfAuth._is_permanent_blockc              
   C   s   t jjsd S | jdkrd S tjdd }d|  }tj	|}d
tjtjdd}tj	|| |stjjddd |d	d
dd||d td | }|r||krtjjddd |dd
dd||d td d S )Nr   captchazauth:user_login_captcha:r      kr   r   zRequire captcharN   rP   r
   r   i  zBad captcha)r   r   Zauth_check_captchafail_try_counterrequestvaluesr[   r   rx   r   joinrandomchoicesstringdigitsr   rZ   r^   r_   abortrq   )r   r6   r   r   Z
db_captchaZnew_captchar   r   r   _auth_check_captcha  s<    

   
   zCmfAuth._auth_check_captchac                 C   s\   |  j d7  _ | j tjjkrPtjjr,d| _ntj tjtjj	j
d | _d| _ |   d S )Nr
   T)Zminutesr   )r   r   r   Zauth_fail_try_countr   r   datetimenow	timedeltar   rb   r   rh   r   r   r   r   r     s    
zCmfAuth.auth_fail_hookc                 C   s   d| _ |   d S )Nr   )r   rh   r   r   r   r   r     s    zCmfAuth.auth_success_hookc              	   C   s   | j r| j dkrdS | j}|rVzt|}W n ttfk
rD   Y dS X |t krVdS tjj}|r| j	r| j	t
j|jd }|| j	 k rdS dS )u   
        Проверка необходимости смены пароля с учетом типа последней авторизации.
        r   FTrr   )r   Zpassword_expires_must_changefloat	TypeErrorr   r)   r   r   password_max_dayspassword_changed_dater   r   rb   r   )r   Zpassword_expires_valueZ
expires_tsr   Zexpire_dater   r   r   need_change_password  s     
zCmfAuth.need_change_passwordc                 C   s"   |  }||_ ||_||| |S r#   )r6   rK   set_pass_hash)r5   r6   hashr"   r   r   r   r   new_from_login_hash_salt  s
    z CmfAuth.new_from_login_hash_saltc           
      C   sl   | d}|d }|dkrZ|dd  \}}}t|}t|}	|	td| |t|kS td| d S )Nr   r   Zpbkdf2_sha256r
   r-   zNot Implemented for )r   r   r   r   r3   r(   NotImplementedError)
r5   r:   Zsecret_hashZ
hash_partsZ	hash_algoZn_itersalt_b64hash_b64Zsalt_bZhash_br   r   r   r     s    


zCmfAuth.check_secretc                 C   s   | j |dddgd}|rd| ||jjrdtjj & tj	j
ddd|id dd||d	 W 5 Q R X |S tjj & tj	j
d
dd|id dd||d	 W 5 Q R X d S )Nr   r6   rl   rL   r   r   rY   r
   )rQ   rR   rT   rS   rU   r   r   r   r   rP   )r[   r   r   rb   r   r   r\   r]   rZ   r^   r_   )r5   r6   r7   r   r   r   r   from_login_password  s.    
   
   zCmfAuth.from_login_passwordc                 C   sR   t jjsd S tjj| dgddgddgdD ]"}|jr*| ||jr*t|j	q*d S )Nz-cmf_created_atr      r   cmf_created_at)rS   Zorder_byslicerM   )
r   r   Zpassword_check_historyrZ   CmfAuthHistoryZslistr   r   ZCmfAuthReusePasswordErrorr   )r   r7   historyr   r   r   check_history   s       
zCmfAuth.check_historyc                 C   s(   t |}t |}| j|||d d S )Nr7   )r0   r1   set_pass_hash_bytes)r   r   r"   r7   
hash_bytes
salt_bytesr   r   r   r     s    

zCmfAuth.set_pass_hashc              	   C   s   |d k	r|  | t| }t| }d| d| | _| j  tjj	| j
d}|r|j  d|_t  |jdd W 5 Q R X d S )Nzpbkdf2_sha256$100000$r   r6   FT)Z	only_data)r   r   rn   rq   r   r   Zset_nowrZ   	CmfPersonr[   r6   Zpassword_must_changer\   r]   rh   )r   r   r   r7   r   r   personr   r   r   r     s    



zCmfAuth.set_pass_hash_bytesc                 C   s   t jS r#   )r   r   )r5   r   r   r   current_auth!  s    zCmfAuth.current_authc                 C   s:   g }t dD ]}|ttjtj  qd|dS )N   r   zutf-8)	rangeappendr   choicer   ascii_lettersr   r   r3   )r5   charsir   r   r   gen_salt%  s    zCmfAuth.gen_salt   c           	      C   s   |  dg |sPttjjj|}tjjj}tjjj}tjjj}| j	||||d}t
|  }td| |d}| j|||o~|d tjj , tjjddd| jidd	| j| jd
d W 5 Q R X |S )uO   
        Генерирует новый пароль
        :return:
        r6   )lengthis_upper_symbol	is_numberis_special_symbolr-   r.   r   reset_passwordr   NrY   r
   )rQ   rR   rT   rS   rU   r   r   r   )Zload_fieldsmaxr   r   Zpassword_min_lengthrb   Zpassword_min_upper_symbolZpassword_min_numbersZpassword_min_special_symbol_generate_passwordr   r   r2   r   r3   r   r   r   r\   r]   rZ   r^   r_   r6   )	r   r   r7   forcer   r   r   r"   r   r   r   r   r   ,  s2    


  
   zCmfAuth.reset_password)r   r   r   r   returnc                 C   s   g }t jt j t j }|r6|t j7 }|tt j |rL|tt j |rb|tt j tj||t	| d}|
| t| d|S )Nr   r   )r   r   r   Zascii_uppercaseZpunctuationr   r   r   r   r/   extendZshuffler   )r   r   r   r   r   Zpassword_dataZlettersZextra_symbolsr   r   r   r  I  s    


zCmfAuth._generate_passwordc                 C   s\   dt j }d|g}t||| tjj & tjj	ddd d|id||dd W 5 Q R X d S )	Nu&   Пароль для доступа к u   Пароль:send_passwordr   rK   rY   r
   )rQ   rR   rS   rT   rU   r   r   r   )
rW   r`   r   r   r   r\   r]   rZ   r^   r_   )r5   r7   rK   rX   Zmsg_contentsr   r   r   r  ^  s    
   zCmfAuth.send_passwordc                 C   sn   ddl m} | }tj||d}|  |jtddd d|ddd}|jd	kr\td
t	|j
ddS )Nr   )session)r6   rg_member_ofT)r?   Zinternalzauth/signup)r6   Zgen_pwd)data   u>   Не удалось создать учётную записьaccess_token)r  )Zrequestsr  rZ   r   rh   ZpostrD   Zstatus_coder   rB   Zcookiesr[   )r5   r6   r  r  sr   rr   r   r   create_personi  s    
zCmfAuth.create_personc              	      s   | j jrZd| _| j jsZ| j D ].}| j | D ]}|  jd| d| 7  _q*q| jj | _t j||}| jjrt	
  tj| | jd  W 5 Q R X |S )Nr   r   r   )rS   r   )groups
is_changedrl   is_nullrb   r   superrh   r   r\   r]   rZ   r   )r   argskwargsr   Zgrp_namer|   	__class__r   r   rh     s    

zCmfAuth.savec                 C   s&   | j jrg S tdd | j dD S )Nc                 S   s   g | ]}| d d qS )r   r   )r   ).0r   r   r   r   
<listcomp>  s     z)CmfAuth.prepare_scope.<locals>.<listcomp>r   )rl   r  r   r   r   r   r   r   prepare_scope  s    zCmfAuth.prepare_scopec                 C   s   |  |}tjdkr|S |d d }zt|}W n  tk
rR   d}t|Y nX | ||}|sd|d d  d}t	| t||S )NFalsers   issuJ   Не удалось прочитать публичный ключ EvaTeamuE   Не удалось валидировать токен от EVA_APP r   !)
r   rW   ZEVA_ACCOUNT_USEr   Zread_crm_pub_keyRuntimeErrorr   r   r   r   )r5   eva_app_tokenrv   r  Zcrm_pub_keyr   r   r   r   r   check_token  s    


zCmfAuth.check_token)usersc             
   O   sj  |  |}|d d }|D ]D}zt|d   }dddddd	d
dg}	d}
|dr| jt|d   |	d}
|
r||
_q| j||	d}
n| j||	d}
|
stj|d}
t	d|  |

  |dpd}t|  p||
_|d	pd}t|  pd|
_|
jjr$i |
_|
js2g |
_||
jkrJ|
j| g |
j|< |d rt	d|| ||
jkr|
j| |
j|= d|
j_|

  W q|d D ]:}t	d| d| d|  |
j| | d|
j_q|d |
_t	d|  t	d|
j  |

  t  t	d|
j  W q tk
r^   td|   Y qX qddiS ) u   
        Метод вызывается из eva_app при синхронизации
        создает и привязывает пользователей
        https://bcrm.carbonsoft.ru/project/Document/DOC-003025#spec-0-ldap
        rs   r   r6   r  rl   r   reg_org_name_listrK   r   Z
is_supportZis_adminNZ	old_loginrL   r   u(   Создали пользователя r   Zcmf_deletedu4   Пользователь {} удален из Eva {}Tr  u,   Добавляем пользователю u    права u    в Eva r   z
user_dict=zuser.groups=zuser.scope=u)   Не удалось обработать resultrY   )r  r'   r   r   r[   r6   rZ   r   r   r   rh   rK   r   r  r  r!  r   formatremover  r   
cmf_commitrl   r   r   )r5   r  r   r  r  rv   r   Z	user_dictr6   _fieldsuserrK   r   Zgrp_coder   r   r   rpc_account_sync_push  sp    

    





zCmfAuth.rpc_account_sync_pushc                O   s  t js
d S dd }t jsd S | |}|d d }|D ]}tjj|d d dgd}	|	s`t }	||	|d  |d d |	_|	  tjj|d dd	gd}
|
st }
||
| ||
_	|d |
_|	|
_
|
  q6tjjd
ddd |D gdD ]}	|	  qddiS )Nc                 S   sF   |D ]<}|dks| ds|dr&qt| |rt| |||  qd S )N)idcodeZext_ipZcmf_Z_id)r   endswithhasattrsetattr)r   Zobj_dictZ
field_namer   r   r   copy_f  s    
z/CmfAuth.rpc_account_plugin_push.<locals>.copy_frs   r   pluginr)  r	   )ext_idrM   r   r0  zNOT INc                 S   s   g | ]}|d  qS )r)  r   )r  r   r   r   r   r  	  s     z3CmfAuth.rpc_account_plugin_push.<locals>.<listcomp>)r   r"  rY   )rW   ZIS_BOX_VERSIONr  rZ   Z	CmfPluginr[   r0  rh   r   r   r/  r   delete)r5   r  Zauth_pluginsr  r  r.  rv   r   r   r/  Zauth_plugin_objr   r   r   rpc_account_plugin_push  s2    



"
zCmfAuth.rpc_account_plugin_pushc                 K   sl   | j tj| jjd tjtjd }ttdtj	}|j
d|  f||dddd| tj|||f| d S )N)Zsecondsr   ZAUTH_SESSION_COOKIE_DOMAINZsession_tokenTLaxr   expiresZsecureZhttponlyZsamesite)Zreauth_dater   r   Zaccess_token_expires_inrb   rW   PROLONG_DAYSgetattrr   host
set_cookieZ	get_tokenr   set_nginx_token)r  responsecookie_kwargsr5  cookie_domainr   r   r   set_session_token  s    $  	zCmfAuth.set_session_tokenc                 K   sL   |j d| jtjd df|tj tjtjtj d dddd| d S )Nr  r
   r   Tr3  r4  )r9  r}   rW   TOKEN_TTL_DAYSr   r   r   r6  )r   r;  r=  r<  r   r   r   set_access_token  s    
  
zCmfAuth.set_access_tokenc                 K   s<   |st j  t jtjd }| jd||dddd| d S )Nr   nginx_auth_tokenpassword123Tr3  r4  )rA  rB  )r   r   r   rW   r?  r9  )r;  r=  r5  r<  r   r   r   r:  .  s        zCmfAuth.set_nginx_tokenu_   Разблокировка учетных записей по истечению времениz	@minutely)Z	only_oncedescriptionZ
system_jobZschedulec                  C   s^   t jjrd S tj } tjjdgdd| gddgd}|s:qZ|D ]}d |_|	  q>t
  qd S )Nr   <r   d   )rM   r   r   )r   r   r   r   r   rZ   r   r   r   rh   r%  )r   Zblocked_usersr   r   r   r   )cron_unblock_users_after_block_expiration;  s    

z1CmfAuth.cron_unblock_users_after_block_expiration)r<   F)T)r   N)r   N)T)N)N)r   NN)FFF)N)N)D__name__
__module____qualname__r&   Z	ts_lengthZjinja2ZEnvironmentZFileSystemLoaderr   r   r   rW   r   rx   Zselect_jinja_autoescapera   propertyr    r"   r,   classmethodr;   rI   rf   rA   ri   ru   staticmethodrB   rw   r'   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r(   boolr  r  r  rh   r  r  r   r(  r2  r>  r@  r:  Zcmf_deferred_jobrF  __classcell__r   r   r  r   r      s   




 





'
f








      


B
!

r   ) r   r   r2   ro   r   r$   r   r)   rE   r   ZCrypto.Cipherr   ZCrypto.Hashr   ZCrypto.PublicKeyr   ZCrypto.Randomr   ZCrypto.Signaturer   ZCrypto.Util.Paddingr   Zcmf.includerK   r   rM   r   Zenumsr   Z
supervisorr   r   r   r   r   r   <module>   s*   