
    z	7j                     *   d Z ddlm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mZmZ  G d d	e          Z G d
 de          Z G d de          Z G d de          Z G d d          ZddZ G d d          ZdS )zWeCom BizMsgCrypt-compatible AES-CBC encryption for callback mode.

Implements the same wire format as Tencent's official ``WXBizMsgCrypt``
SDK so that WeCom can verify, encrypt, and decrypt callback payloads.
    )annotationsN)Optional)ElementTree)default_backend)Cipher
algorithmsmodesc                      e Zd ZdS )WeComCryptoErrorN__name__
__module____qualname__     J/home/rurouni/.hermes/hermes-agent/plugins/platforms/wecom/wecom_crypto.pyr   r              Dr   r   c                      e Zd ZdS )SignatureErrorNr   r   r   r   r   r      r   r   r   c                      e Zd ZdS )DecryptErrorNr   r   r   r   r   r      r   r   r   c                      e Zd ZdS )EncryptErrorNr   r   r   r   r   r   "   r   r   r   c                  B    e Zd ZdZed	d            Zed
d            ZdS )PKCS7Encoder    textbytesreturnc                    | j         t          |          | j         z  z
  }|dk    r| j         }t          |g          |z  }||z   S )Nr   )
block_sizelenr   )clsr   amount_to_padpads       r   encodezPKCS7Encoder.encode)   sK    #d))cn*DEANM]O$$}4czr   	decryptedc                    |st          d          |d         }|dk     s|| j        k    rt          d          || d          t          |g          |z  k    rt          d          |d |          S )Nzempty decrypted payload   zinvalid PKCS7 paddingzmalformed PKCS7 padding)r   r!   r   )r#   r'   r%   s      r   decodezPKCS7Encoder.decode1   s     	:8999m77cCN**6777cTUUucU||c11189993$r   N)r   r   r   r   )r'   r   r   r   )r   r   r   r!   classmethodr&   r+   r   r   r   r   r   &   sW        J   [       [     r   r   tokenstr	timestampnonceencryptr   c                    t          | |||g          }t          j        d                    |                              d                                                    S )N utf-8)sortedhashlibsha1joinr&   	hexdigest)r-   r/   r0   r1   partss        r   _sha1_signaturer;   =   sL    E9eW566E<--g6677AACCCr   c                  V    e Zd ZdZddZddZddZdddZddZe	d d!d            Z
dS )"WXBizMsgCryptzKMinimal WeCom callback crypto helper compatible with BizMsgCrypt semantics.r-   r.   encoding_aes_key
receive_idc                ,   |st          d          |st          d          t          |          dk    rt          d          |st          d          || _        || _        t	          j        |dz             | _        | j        d d         | _        d S )Nztoken is requiredzencoding_aes_key is required+   z!encoding_aes_key must be 43 charszreceive_id is required=   )
ValueErrorr"   r-   r?   base64	b64decodekeyiv)selfr-   r>   r?   s       r   __init__zWXBizMsgCrypt.__init__E   s     	20111 	=;<<<  B&&@AAA 	75666
$#$4s$:;;(3B3-r   msg_signaturer/   r0   echostrr   c                \    |                      ||||          }|                    d          S )Nr4   )decryptr+   )rI   rK   r/   r0   rL   plains         r   
verify_urlzWXBizMsgCrypt.verify_urlT   s+    ]IugFF||G$$$r   r1   r   c                   t          | j        |||          }||k    rt          d          	 t          j        |          }n%# t
          $ r}t          d|           |d }~ww xY w	 t          t          j	        | j
                  t          j        | j                  t                                }|                                }	|	                    |          |	                                z   }
t$                              |
          }|dd          }t)          j        t-          j        d|d d                   d                   }|dd|z            }|d|z   d                              d          }n/# t0          $ r  t
          $ r}t          d	|           |d }~ww xY w|| j        k    rt          d
          |S )Nzsignature mismatchzinvalid base64 payload: backendrC   I   r   r4   zdecrypt failed: zreceive_id mismatch)r;   r-   r   rE   rF   	Exceptionr   r   r   AESrG   r	   CBCrH   r   	decryptorupdatefinalizer   r+   socketntohlstructunpackr   r?   )rI   rK   r/   r0   r1   expectedcipher_textexccipherrY   paddedrO   content
xml_lengthxml_contentr?   s                   r   rN   zWXBizMsgCrypt.decryptX   s   "4:y%II}$$ !5666	J *733KK 	J 	J 	J?#??@@cI	J	BJN4844ei6H6HRaRcRcdddF((**I%%k22Y5G5G5I5IIF ''//EBCCjGfmC!&E&Ea&HIIJ!!A
N"23K Z188AAJJ 	 	 	 	B 	B 	B7#7788cA	B ((4555s0   A 
A%A  A%)DE: :F&F!!F&N	plaintextOptional[str]c                J   |p|                                  }|p:t          t          t          d                                                              }|                     |                    d                    }t          | j        |||          }t          j
        d          }|t          j        |d          _        |t          j        |d          _        |t          j        |d          _        |t          j        |d          _        t          j        |d	          S )
Ntimer4   xmlEncryptMsgSignature	TimeStampNonceunicode)encoding)_random_noncer.   int
__import__rk   _encrypt_bytesr&   r;   r-   ETElement
SubElementr   tostring)rI   rh   r0   r/   r1   	signatureroots          r   r1   zWXBizMsgCrypt.encryptr   s    -++--DSF););)@)@)B)B%C%C!D!D	%%i&6&6w&?&?@@#DJ	5'JJ	z%  .5dI&&+3<dN++009dK((-,1dG$$){4)4444r   rawc                   	 t          j        d          }t          j        dt	          j        t          |                              }||z   |z   | j                            d          z   }t                              |          }t          t          j        | j                  t          j        | j                  t#                                }|                                }|                    |          |                                z   }t+          j        |                              d          S # t0          $ r}	t3          d|	           |	d }	~	ww xY w)NrC   rT   r4   rR   zencrypt failed: )osurandomr^   packr\   htonlr"   r?   r&   r   r   r   rW   rG   r	   rX   rH   r   	encryptorrZ   r[   rE   	b64encoder+   rV   r   )
rI   r}   random_prefixmsg_lenpayloadrd   rc   r   	encryptedrb   s
             r   rv   zWXBizMsgCrypt._encrypt_bytes~   s0   
	BJrNNMk#v|CHH'='=>>G#g-3do6L6LW6U6UUG!((11FJN4844ei6H6HRaRcRcdddF((**I!((0093E3E3G3GGI#I..55g>>> 	B 	B 	B7#7788cA	Bs   D5D8 8
EEE
   lengthrt   c                d    dd                     fdt          |           D                       S )N>0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZr3   c              3  @   K   | ]}t          j                  V  d S )N)secretschoice).0_alphabets     r   	<genexpr>z.WXBizMsgCrypt._random_nonce.<locals>.<genexpr>   s-      GGAw~h//GGGGGGr   )r8   range)r   r   s    @r   rs   zWXBizMsgCrypt._random_nonce   s5    SwwGGGGvGGGGGGr   )r-   r.   r>   r.   r?   r.   )
rK   r.   r/   r.   r0   r.   rL   r.   r   r.   )
rK   r.   r/   r.   r0   r.   r1   r.   r   r   )NN)rh   r.   r0   ri   r/   ri   r   r.   )r}   r   r   r.   )r   )r   rt   r   r.   )r   r   r   __doc__rJ   rP   rN   r1   rv   staticmethodrs   r   r   r   r=   r=   B   s        UU       % % % %   4
5 
5 
5 
5 
5B B B B H H H H \H H Hr   r=   )
r-   r.   r/   r.   r0   r.   r1   r.   r   r.   )r   
__future__r   rE   r6   r   r   r\   r^   typingr   	xml.etreer   rw   cryptography.hazmat.backendsr   &cryptography.hazmat.primitives.ciphersr   r   r	   rV   r   r   r   r   r   r;   r=   r   r   r   <module>r      s    # " " " " "   				          ' ' ' ' ' ' 8 8 8 8 8 8 L L L L L L L L L L	 	 	 	 	y 	 	 		 	 	 	 	% 	 	 		 	 	 	 	# 	 	 		 	 	 	 	# 	 	 	               .D D D D
LH LH LH LH LH LH LH LH LH LHr   