o
    ^                     @   s^  d 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	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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!m"Z"m#Z#m$Z$m%Z%m&Z& ej'( rddl)m*Z* nddl+m*Z* zddl,m-Z- e.e-doe-/ Z0W n e1y   d	Z0Y nw d
Z2dZ3dddddg dZ4g dZ5dZ6dZ7dZ8dZ9dZ:dZ;dZ<G dd de=Z>G dd de?de4@ ZAG dd de?dg dZBG dd deCZDd^ddZEdd ZFd d! ZGd"d# ZHd$d% ZId&d' ZJd(d) ZKd*d+ ZLd,d- ZMe"d.d.d	d/ZNe d0d1ZOe$d2d3d4ZPe d5d6ZQe#d7d8ZRe$d9d9d:ZSe"d;d.d	d/ZTe"d<d=d	d/ZUeVd>d?ZWe"d@dAd	d/ZXe$dBdBdCZYe d9d9ZZe dDdEZ[e dFdGZ\e$dHdHdCZ]e dIdJdKdL dMZ^e!dNdOZ_G dPdQ dQeZ`G dRdS dSe`ZaG dTdU dUe`ZbG dVdW dWeZcG dXdY dYeZddZd[ Zed\d] ZfeaZgdS )_a  
Parsing for Tor hidden service descriptors as described in Tor's `version 2
<https://gitweb.torproject.org/torspec.git/tree/rend-spec-v2.txt>`_ and
`version 3 <https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt>`_
rend-spec.

Unlike other descriptor types these describe a hidden service rather than a
relay. They're created by the service, and can only be fetched via relays with
the HSDir flag.

These are only available through the Controller's
:func:`~stem.control.Controller.get_hidden_service_descriptor` method.

**Module Overview:**

::

  BaseHiddenServiceDescriptor - Common parent for hidden service descriptors
    |- HiddenServiceDescriptorV2 - Version 2 hidden service descriptor
    +- HiddenServiceDescriptorV3 - Version 3 hidden service descriptor
         |- address_from_identity_key - convert an identity key to address
         |- identity_key_from_address - convert an address to identity key
         +- decrypt - decrypt and parse encrypted layers

  OuterLayer - First encrypted layer of a hidden service v3 descriptor
  InnerLayer - Second encrypted layer of a hidden service v3 descriptor

.. versionadded:: 1.4.0
    N)CertType)ExtensionTypeEd25519ExtensionEd25519CertificateEd25519CertificateV1)PGP_BLOCK_END
Descriptor_descriptor_content_descriptor_components_read_until_keywords_bytes_for_block_value_values_parse_simple_line_parse_if_present_parse_int_line_parse_timestamp_line_parse_key_block_random_date_random_crypto_blob)	lru_cache)backendx25519_supportedF)rendezvous-service-descriptorversionpermanent-keysecret-id-partpublication-timeprotocol-versions	signaturehs-descriptordescriptor-lifetimedescriptor-signing-key-certrevision-countersuperencryptedr   )
identifieraddressport	onion_keyservice_keyZintro_authentication)introduction-point
ip-address
onion-port	onion-keyservice-key      s   .onion checksum       c                   @      e Zd ZdZdS )DecryptionFailurezM
  Failure to decrypt the hidden service descriptor's introduction-points.
  N__name__
__module____qualname____doc__ r;   r;   @/usr/lib/python3/dist-packages/stem/descriptor/hidden_service.pyr5          r5   c                   @   r4   )IntroductionPointsa  
  Introduction point for a v2 hidden service.

  :var str identifier: hash of this introduction point's identity key
  :var str address: address of this introduction point
  :var int port: port where this introduction point is listening
  :var str onion_key: public key for communicating with this introduction point
  :var str service_key: public key for communicating with this hidden service
  :var list intro_authentication: tuples of the form (auth_type, auth_data) for
    establishing a connection
  Nr6   r;   r;   r;   r<   r>      r=   r>   c                   @   s   e Zd ZdZedd ZedddZedddZd	d
 Zdd Z	dd Z
dd Zdd ZedddZedd Zdd Zdd Zdd ZdS ) IntroductionPointV3a  
  Introduction point for a v3 hidden service.

  .. versionadded:: 1.8.0

  :var list link_specifiers: :class:`~stem.client.datatype.LinkSpecifier` where this service is reachable
  :var unicode onion_key_raw: base64 ntor introduction point public key
  :var stem.descriptor.certificate.Ed25519Certificate auth_key_cert: cross-certifier of the signing key with the auth key
  :var unicode enc_key_raw: base64 introduction request encryption key
  :var stem.descriptor.certificate.Ed25519Certificate enc_key_cert: cross-certifier of the signing key by the encryption key
  :var str legacy_key_raw: base64 legacy introduction point RSA public key
  :var str legacy_key_cert: base64 cross-certifier of the signing key by the legacy key
  c                 C   s  t | d}ttd|}td|}|dr|dd nd}|d d \}}}t|}|d	kr7td
| td|}|drG|dd nd}	|d d \}}}
t|
}
|d	kratd| d|v rm|d d d nd}d|v r{|d d d nd}t||||	|
||S )a  
    Parses an introduction point from its descriptor content.

    :param str content: descriptor content to parse

    :returns: :class:`~stem.descriptor.hidden_service.IntroductionPointV3` for the descriptor content

    :raises: **ValueError** if descriptor content is malformed
    Fr+   r.   zntor    Nzauth-keyr   zED25519 CERTz<Expected auth-key to have an ed25519 certificate, but was %szenc-keyzenc-key-certz@Expected enc-key-cert to have an ed25519 certificate, but was %sz
legacy-keyr1   zlegacy-key-cert)r
   r?   _parse_link_specifiersr   
startswithr   Zfrom_base64
ValueError)contententrylink_specifiersZonion_key_liner)   _
block_typeauth_key_certZenc_key_lineenc_keyenc_key_cert
legacy_keylegacy_key_certr;   r;   r<   parse   s"   




zIntroductionPointV3.parseNc                 C   s   t jjddstdt jj|std| t jj| r)t j	j
| |g}nt jj| r:t j	j
| |g}ntd|  tj|ddddddS )a7  
    Simplified constructor for a single address/port link specifier.

    :param str address: IPv4 or IPv6 address where the service is reachable
    :param int port: port where the service is reachable
    :param datetime.datetime expiration: when certificates should expire
    :param str onion_key: encoded, X25519PublicKey, or X25519PrivateKey onion key
    :param str enc_key: encoded, X25519PublicKey, or X25519PrivateKey encryption key
    :param str auth_key: encoded, Ed25519PublicKey, or Ed25519PrivateKey authentication key
    :param cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey signing_key: service signing key

    :returns: :class:`~stem.descriptor.hidden_service.IntroductionPointV3` with these attributes

    :raises: **ValueError** if the address, port, or keys are malformed
    Ted25519LIntroduction point creation requires the cryptography module ed25519 support'%s' is an invalid portz('%s' is not a valid IPv4 or IPv6 addressN)
expirationr)   rJ   auth_keysigning_key)stemprereqis_crypto_availableImportErrorutil
connectionis_valid_portrC   is_valid_ipv4_addressclientdatatypeZ
LinkByIPv4Zis_valid_ipv6_addressZ
LinkByIPv6r?   create_for_link_specifiers)r'   r(   rS   r)   rJ   rT   rU   rF   r;   r;   r<   create_for_address   s   z&IntroductionPointV3.create_for_addressc                 C   s"  t jjddstdddlm} ddlm} |du r)tj	 tj
t jjjd }t jjtt j|r6|n| }t jjtt j|rJ|n| }t j|rX|n| }|ra|n| }ttjdt j|g}ttj|d	|||d
}	ttj|d	|||d
}
t| ||	||
ddS )al  
    Simplified constructor. For more sophisticated use cases you can use this
    as a template for how introduction points are properly created.

    :param list link_specifiers: series of stem.client.datatype.LinkSpecifier where the service is reachable
    :param datetime.datetime expiration: when certificates should expire
    :param str onion_key: encoded, X25519PublicKey, or X25519PrivateKey onion key
    :param str enc_key: encoded, X25519PublicKey, or X25519PrivateKey encryption key
    :param str auth_key: encoded, Ed25519PublicKey, or Ed25519PrivateKey authentication key
    :param cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey signing_key: service signing key

    :returns: :class:`~stem.descriptor.hidden_service.IntroductionPointV3` with these attributes

    :raises: **ValueError** if the address, port, or keys are malformed
    TrO   rQ   r   Ed25519PrivateKeyX25519PrivateKeyN)Zhoursr0   )rU   )rV   rW   rX   rY   1cryptography.hazmat.primitives.asymmetric.ed25519rc   0cryptography.hazmat.primitives.asymmetric.x25519re   datetimeZutcnowZ	timedelta
descriptorcertificateZDEFAULT_EXPIRATION_HOURSrZ   	str_tools_to_unicodebase64	b64encode_pubkey_bytesgenerater   r   HAS_SIGNING_KEYr   r   ZHS_V3_INTRO_AUTHZHS_V3_NTOR_ENCr?   )rF   rS   r)   rJ   rT   rU   rc   re   
extensionsrI   rK   r;   r;   r<   r`      s   ((z.IntroductionPointV3.create_for_link_specifiersc                 C   s   g }t jjjjt| j}|ddd | jD  }|	dt j
jt|  |	d| j  |	d| jjdd  | jrI|	d	| j  |	d
| jjdd  | jr`|	d| j  | jrk|	d| j  d|S )zx
    Descriptor representation of this introduction point.

    :returns: **str** for our descriptor representation
        c                 S   s   g | ]}|  qS r;   )pack).0lr;   r;   r<   
<listcomp>!      z.IntroductionPointV3.encode.<locals>.<listcomp>zintroduction-point %szonion-key ntor %sz	auth-key
TZpemzenc-key ntor %szenc-key-cert
zlegacy-key
zlegacy-key-cert

)rV   r^   r_   SizeCHARrt   lenrF   joinappendrZ   rk   rl   rm   rn   onion_key_rawrI   	to_base64enc_key_rawrK   legacy_key_rawrM   )selflinesZ
link_countrF   r;   r;   r<   encode  s   
zIntroductionPointV3.encodec                 C      t j| jddS )a-  
    Provides our ntor introduction point public key.

    :returns: ntor :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey`

    :raises:
      * **ImportError** if required the cryptography module is unavailable
      * **EnvironmentError** if OpenSSL x25519 unsupported
    Tx25519)r?   _key_asr   r   r;   r;   r<   r)   3     zIntroductionPointV3.onion_keyc                 C   s   t j| jjddS )a/  
    Provides our authentication certificate's public key.

    :returns: :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`

    :raises:
      * **ImportError** if required the cryptography module is unavailable
      * **EnvironmentError** if OpenSSL x25519 unsupported
    TrO   )r?   r   rI   keyr   r;   r;   r<   rT   @  s   zIntroductionPointV3.auth_keyc                 C   r   )a  
    Provides our encryption key.

    :returns: encryption :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey`

    :raises:
      * **ImportError** if required the cryptography module is unavailable
      * **EnvironmentError** if OpenSSL x25519 unsupported
    Tr   )r?   r   r   r   r;   r;   r<   rJ   M  r   zIntroductionPointV3.enc_keyc                 C   r   )a1  
    Provides our legacy introduction point public key.

    :returns: legacy :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey`

    :raises:
      * **ImportError** if required the cryptography module is unavailable
      * **EnvironmentError** if OpenSSL x25519 unsupported
    Tr   )r?   r   r   r   r;   r;   r<   rL   Z  r   zIntroductionPointV3.legacy_keyFc                 C   s   | d u s|s
|s
| S t j std|r)tstdddlm} |t	
| S |rAt jjdds6tdddlm} || S d S )	Nzcryptography module unavailablezOpenSSL x25519 unsupportedr   )X25519PublicKeyTrO   z cryptography ed25519 unsupported)Ed25519PublicKey)rV   rW   rX   rY   X25519_AVAILABLEEnvironmentErrorrg   r   Zfrom_public_bytesrm   	b64decoderf   r   )valuer   rP   r   r   r;   r;   r<   r   g  s   

zIntroductionPointV3._key_asc              
   C   s   zt | } W n ty } ztd|| f d }~ww g }tjjjj	| \}} t
|D ]}tjjj	| \}} || q-| rGtd|  |S )Nz3Unable to base64 decode introduction point (%s): %sz*Introduction point had excessive data (%s))rm   r   	ExceptionrC   rV   r^   r_   r{   r|   poprangeZLinkSpecifierr   )rD   excrF   countiZlink_specifierr;   r;   r<   rA     s   z*IntroductionPointV3._parse_link_specifiersc                 C   s   t | dst|  | _| jS )N_hash)hasattrhashr   r   r   r;   r;   r<   __hash__  s   
zIntroductionPointV3.__hash__c                 C      t |trt| t|kS dS NF)
isinstancer?   r   r   otherr;   r;   r<   __eq__     zIntroductionPointV3.__eq__c                 C   
   | |k S Nr;   r   r;   r;   r<   __ne__     
zIntroductionPointV3.__ne__)NNNNNFF)r7   r8   r9   r:   staticmethodrN   ra   r`   r   r)   rT   rJ   rL   r   rA   r   r   r   r;   r;   r;   r<   r?      s(    
%%
r?   )rF   r   rI   r   rK   r   rM   c                   @   s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )AuthorizedClientz
  Client authorized to use a v3 hidden service.

  .. versionadded:: 1.8.0

  :var str id: base64 encoded client id
  :var str iv: base64 encoded randomized initialization vector
  :var str cookie: base64 encoded authentication cookie
  Nc                 C   s   t jj|r|n
ttdd| _	t jj|r|n
ttdd| _
t jj|r2|n
ttdd| _d S )N      =r2   )rV   rZ   rk   rl   rm   rn   osurandomrstripidivcookie)r   r   r   r   r;   r;   r<   __init__  s   **.zAuthorizedClient.__init__c                 C   s   t jj| dddddS )Nr   r   r   T)cache)rV   rZ   Z
_hash_attrr   r;   r;   r<   r     s   zAuthorizedClient.__hash__c                 C   r   r   )r   r   r   r   r;   r;   r<   r     r   zAuthorizedClient.__eq__c                 C   r   r   r;   r   r;   r;   r<   r     r   zAuthorizedClient.__ne__)NNN)r7   r8   r9   r:   r   r   r   r   r;   r;   r;   r<   r     s    

r   c                 k   s    |du rt }	 td| d}|t kr"tddd }|t|| d7 }|r@|d dr1|dd }|td||fi |V  ndS q)	as  
  Iterates over the hidden service descriptors in a file.

  :param file descriptor_file: file with descriptor content
  :param class desc_type: BaseHiddenServiceDescriptor subclass
  :param bool validate: checks the validity of the descriptor's content if
    **True**, skips these checks otherwise
  :param dict kwargs: additional arguments for the descriptor constructor

  :returns: iterator for :class:`~stem.descriptor.hidden_service.HiddenServiceDescriptorV2`
    instances in the file

  :raises:
    * **ValueError** if the contents is malformed and validate is **True**
    * **IOError** if the file can't be read
  NTr    r0   r   s   @typers   )HiddenServiceDescriptorV2r   r   splitrB   bytesr~   )Zdescriptor_fileZ	desc_typevalidatekwargsZdescriptor_contentZblock_end_prefixr;   r;   r<   _parse_file  s   r   c                 C   s   |  dr| dr| dd } zt| }W n   tdt|tt k r/tdt| |d t }|tt  }|t d  }t|||||\}	}
||
|kr]td||
|f |		 }|
||  }tjj|S )Nz-----BEGIN MESSAGE-----
z
-----END MESSAGE-----   iz*Unable to decode encrypted block as base64z)Encrypted block malformed (only %i bytes)z'Malformed mac (expected %s, but was %s))rB   endswithrm   r   rC   r}   SALT_LENMAC_LEN_layer_cipher	decryptorupdatefinalizerV   rZ   rk   rl   )Zencrypted_blockconstantrevision_countersubcredentialblinded_key	encryptedsalt
ciphertextZexpected_macciphermac_forr   	plaintextr;   r;   r<   _decrypt_layer  s"   r   c                 C   sh   t d}t|||||\}}| }|| |  }	t||	 ||	 }
ddt	j
j|
d S )Nr2   s0   -----BEGIN MESSAGE-----
%s
-----END MESSAGE-----   
@   )r   r   r   	encryptorr   r   rm   rn   r~   rV   rZ   rk   Z_split_by_length)r   r   r   r   r   r   r   r   r   r   Zencodedr;   r;   r<   _encrypt_layer  s   
r   c                    s   ddl m}m}m} ddlm} t|| t	d| | |  }	|	
tt t }
|
d t }|
ttt  }|
tt d  }|||||| }t	dt|| t	dt| |  | fddfS )Nr   Cipher
algorithmsmodesdefault_backendz>Qc                    s   t  |   S r   )hashlibsha3_256digest)r   Z
mac_prefixr;   r<   <lambda>  s    z_layer_cipher.<locals>.<lambda>)&cryptography.hazmat.primitives.ciphersr   r   r   cryptography.hazmat.backendsr   r   Z	shake_256structrt   r   	S_KEY_LENS_IV_LENr   AESCTRr}   )r   r   r   r   r   r   r   r   r   ZkdfkeysZ
secret_keyZ	secret_ivZmac_keyr   r;   r   r<   r     s   "(r   c                 C   sf   t d|}zdd |dD }W n ty   td| w |D ]}|dkr-td| q!|| _d S )Nr   c                 S   s   g | ]}t |qS r;   )int)ru   rE   r;   r;   r<   rw     rx   z1_parse_protocol_versions_line.<locals>.<listcomp>,zEprotocol-versions line has non-numeric versoins: protocol-versions %sr   z/protocol-versions must be positive integers: %s)r   r   rC   protocol_versions)ri   entriesr   Zversionsvr;   r;   r<   _parse_protocol_versions_line  s   

r   c                 C   sb   |d d \}}}|r|dkrt d| || _g | _zt|| _W d S  ty0   t d| w )Nintroduction-pointsr   MESSAGEzI'introduction-points' should be followed by a MESSAGE block, but was a %sz6'introduction-points' isn't base64 encoded content:
%s)rC   introduction_points_encodedintroduction_points_authr   introduction_points_content	TypeError)ri   r   rG   rH   block_contentsr;   r;   r<   _parse_introduction_points_line'  s   r   c                 C   s^   i }t d|D ]"}| }t|dk rtd| t|d |d |d ||d < q|| _d S )Nauth-client   zCauth-client should have a client-id, iv, and cookie: auth-client %sr   r0   r1   )r   r   r}   rC   r   clients)ri   r   r   r   Z
value_compr;   r;   r<   _parse_v3_outer_clients6  s   "
r   c                 C   sL   t d|g }}|dD ]}| std| |t| q|| _d S )Ncreate2-formatsr   z:create2-formats should only contain integers, but was '%s')r   r   isdigitrC   r   r   formats)ri   r   r   r   rE   r;   r;   r<   _parse_v3_inner_formatsF  s   
r   c                 C   sz   t | dr;g }| j}|r4|dd}|dkr$|d | ||d d  fn|df\}}|t| |s|| _| `d S d S )N_unparsed_introduction_points   
introduction-point 
   r0    )r   r   findr   r?   rN   introduction_points)ri   r   r  Z	remainingdivrD   r;   r;   r<   _parse_v3_introduction_pointsR  s   
0r  r   )Zallow_negativer   descriptor_idr   permanent_keyRSA PUBLIC KEYr   secret_id_partr   	publishedr   	SIGNATUREr!   r"   lifetimer#   signing_certr$   r   r%   r   desc-auth-type	auth_typedesc-auth-ephemeral-keyephemeral_keyr   intro-auth-required
intro_authc                 C   s
   |  dS )Nr   )r   )r   r;   r;   r<   r   s  s   
 r   )funcsingle-onion-serviceis_single_servicec                   @   r4   )BaseHiddenServiceDescriptorz;
  Hidden service descriptor.

  .. versionadded:: 1.8.0
  Nr6   r;   r;   r;   r<   r  w  r=   r  c                       s   e Zd ZdZdZdefdefdefdefde	fg e
fdefg efdefdefd
Zeeeee	e
eedZeddd	ZedddZd fdd	Ze dddZedd Zedd Zedd Z  ZS )r   a  
  Version 2 hidden service descriptor.

  :var str descriptor_id: **\*** identifier for this descriptor, this is a base32 hash of several fields
  :var int version: **\*** hidden service descriptor version
  :var str permanent_key: **\*** long term key of the hidden service
  :var str secret_id_part: **\*** hash of the time period, cookie, and replica
    values so our descriptor_id can be validated
  :var datetime published: **\*** time in UTC when this descriptor was made
  :var list protocol_versions: **\*** list of **int** versions that are supported when establishing a connection
  :var str introduction_points_encoded: raw introduction points blob
  :var list introduction_points_auth: **\*** tuples of the form
    (auth_method, auth_data) for our introduction_points_content
    (**deprecated**, always **[]**)
  :var bytes introduction_points_content: decoded introduction-points content
    without authentication data, if using cookie authentication this is
    encrypted
  :var str signature: signature of the descriptor content

  **\*** attribute is either required when we're parsed with validation or has
  a default value, others are left as **None** if undefined

  .. versionchanged:: 1.6.0
     Moved from the deprecated `pycrypto
     <https://www.dlitz.net/software/pycrypto/>`_ module to `cryptography
     <https://pypi.org/project/cryptography/>`_ for validating signatures.

  .. versionchanged:: 1.6.0
     Added the **skip_crypto_validation** constructor argument.
  zhidden-service-descriptorN)
r  r   r  r	  r
  r   r   r   r   r   )r   r   r   r   r   r   r   r   r;   Fc              
   C   sF   |r	t d| j t||dddtdfddt fdd	fd
tdffS )NzSigning of %s not implemented)r   Z y3olqqblqw2gbh6phimfuiroechjjafa)r   2r   r  )r   Z e24kgecavwsznj7gpbktqsiwgvngsf4er   )r   z2,3)r   z.
-----BEGIN MESSAGE-----
-----END MESSAGE-----r   r  )NotImplementedErrorr7   r	   r   r   )clsattrexcludesignr;   r;   r<   rD     s   

	z!HiddenServiceDescriptorV2.contentTc                 C   s   | |  ||||| dS )N)r   skip_crypto_validationrD   )r  r  r  r   r  r;   r;   r<   create  s   z HiddenServiceDescriptorV2.createc           	         s  t t| j|| d t||dd}|rtD ]}||vr"td| ||v r4t|| dkr4td| qdt| d krCtd	d
t| d krQtd| 	|| |st
j r| | j| j}| dd}t|  }||krtd||f d S d S d S || _d S )NZ	lazy_loadr   )Znon_ascii_fields0Hidden service descriptor must have a '%s' entryr0   BThe '%s' entry can only appear once in a hidden service descriptorr   r   zQHidden service descriptor must start with a 'rendezvous-service-descriptor' entryr   r   ;Hidden service descriptor must end with a 'signature' entryzrendezvous-service-descriptor z
signature
zHDecrypted digest does not match local digest (calculated: %s, local: %s))superr   r   r
   REQUIRED_V2_FIELDSrC   r}   listr   _parserV   rW   rX   Z_digest_for_signaturer  r   Z_content_ranger   sha1Z	hexdigestupper_entries)	r   raw_contentsr   r  r   keywordZsigned_digestZdigest_contentZcontent_digest	__class__r;   r<   r     s.   
z"HiddenServiceDescriptorV2.__init__c              
   C   s   | j }|sg S |rctj stdz	tjj|}W n ty- } ztd| d}~ww t	t
|dd d}|tkrEt||}n|tkrPt||}n	td|ttf |dsbtd	n	|dsltd
t|S )a  
    Provided this service's introduction points.

    :returns: **list** of :class:`~stem.descriptor.hidden_service.IntroductionPoints`

    :raises:
      * **ValueError** if the our introduction-points is malformed
      * **DecryptionFailure** if unable to decrypt this field
    z?Decrypting introduction-points requires the cryptography modulez:authentication_cookie must be a base64 encoded string (%s)Nr   r0   r2   zfUnrecognized authentication type '%s', currently we only support basic auth (%s) and stealth auth (%s)   introduction-point zGUnable to decrypt the introduction-points, maybe this is the wrong key?zWintroduction-points content is encrypted, you need to provide its authentication_cookie)r   rV   rW   rX   r5   rZ   rk   Z_decode_b64r   r   binasciihexlify
BASIC_AUTHr   _decrypt_basic_authSTEALTH_AUTH_decrypt_stealth_authrB   _parse_introduction_points)r   authentication_cookierD   r   Zauthentication_typer;   r;   r<   r    s0   



z-HiddenServiceDescriptorV2.introduction_pointsc              
      s  ddl m}m}m} ddlm} ztt| dd d}W n t	y2   t
dt| dd  w |d d }| dd|    fd	d
td|dD }| d| d| d  }	| d| d d  }
t||	  d d }|D ]J\}}||kr|qs||||dt|	 | }| }|||  }|||||	| }| }||
|  }|dr|  S qs| S )Nr   r   r   r0   r1   r2   zaWhen using basic auth the content should start with a number of blocks but wasn't a hex digit: %s   c                    s0   g | ]} ||d    |d  |d  fqS )   r9  r;   ru   r   Zclient_entriesr;   r<   rw   #  s   0 zAHiddenServiceDescriptorV2._decrypt_basic_auth.<locals>.<listcomp>r:      r0  )r   r   r   r   r   r   r   r1  r2  rC   r5   r   r   r)  r   r   r   r}   r   r   r   rB   )rD   r8  r   r   r   r   Zclient_blocksZclient_entries_lengthZclient_keysr   r   Z	client_idZentry_idZencrypted_session_keyr   r   Zsession_keyZ	decryptedr;   r<  r<   r4    s4   "
z-HiddenServiceDescriptorV2._decrypt_basic_authc           
      C   sn   ddl m}m}m} ddlm} | dd | dd  }}|||||| }| }	|		||	
  S )Nr   r   r   r0      )r   r   r   r   r   r   r   r   r   r   r   )
rD   r8  r   r   r   r   r   r   r   r   r;   r;   r<   r6  A  s   z/HiddenServiceDescriptorV2._decrypt_stealth_authc                 C   s  g }t | }	 dtd|dd} | s	 |S tt}t| d}t| D ]\}}|d \}}}	|t	v rEt
|dkrEtd|t
|f |dkrN||d	< q&|d
krdtjj|s_td| ||d< q&|dkr|tjj|sutd| t||d< q&|dkr|	|d< q&|dkr|	|d< q&|dkrg }
|D ]!\}}}d|vrtd| |ddd \}}|
||f qq&|tdi | q)zU
    Provides the parsed list of IntroductionPoints for the unencrypted content.
    Trs   r+   )Zignore_firstFr   r0   zO'%s' can only appear once in an introduction-point block, but appeared %i timesr&   r,   z'%s' is an invalid IPv4 addressr'   r-   rR   r(   r.   r)   r/   r*   zintro-authenticationr   zHWe expected 'intro-authentication [auth_type] [auth_data]', but had '%s'Nr1   r;   )ioBytesIOr~   r   dictINTRODUCTION_POINTS_ATTRr
   r'  items SINGLE_INTRODUCTION_POINT_FIELDSr}   rC   rV   rZ   r[   r]   r\   r   r   r   r>   )rD   r  Z
content_ior  r   r-  valuesr   rH   r   Zauth_entriesZ
auth_valuerG   r  Z	auth_datar;   r;   r<   r7  M  sJ   
'




z4HiddenServiceDescriptorV2._parse_introduction_points)Nr;   F)Nr;   TFr   r   )r7   r8   r9   r:   TYPE_ANNOTATION_NAME)_parse_rendezvous_service_descriptor_line_parse_v2_version_line_parse_permanent_key_line_parse_secret_id_part_line_parse_publication_time_liner   r   _parse_v2_signature_line
ATTRIBUTESPARSER_FOR_LINEclassmethodrD   r   r   r   r  r   r4  r6  r7  __classcell__r;   r;   r.  r<   r     sH    (
+
r   c                       s   e Zd ZdZdZdefdefdefdefde	fde
fdZeeeee	e
dZeddd	ZedddZd fdd	Zdd ZedddZedd Zedd Z  ZS )HiddenServiceDescriptorV3a  
  Version 3 hidden service descriptor.

  :var int version: **\*** hidden service descriptor version
  :var int lifetime: **\*** minutes after publication this descriptor is valid
  :var stem.descriptor.certificate.Ed25519Certificate signing_cert: **\*** cross-certifier for the short-term descriptor signing key
  :var int revision_counter: **\*** descriptor revision number
  :var str superencrypted: **\*** encrypted HS-DESC-ENC payload
  :var str signature: **\*** signature of this descriptor

  **\*** attribute is either required when we're parsed with validation or has
  a default value, others are left as **None** if undefined

  .. versionadded:: 1.8.0
  zhidden-service-descriptor-3N)r   r  r  r   r%   r   r    r;   Fc                 C   s  t jjddstdt j std|
r$t|
dkr$tdt|
 ddlm} |r.|nt	j
|d	}|r8|n| }|r@|n| }|	rH|	ntt }	|
rUt||
nd
}t||}|rhd|v rh|dnd}|svtj
|||	||d}|sttjd|g}ttj||d}|
rt| |||
nd|_t||dddd|jdd fdt|	fdd||	|| ffdd }|r|dt j j!"| 7 }|S d|vrt j#j$j%| }|dt&'|(|)d 7 }|S )a'  
    Hidden service v3 descriptors consist of three parts:

      * InnerLayer, which most notably contain introduction points where the
        service can be reached.

      * OuterLayer, which encrypts the InnerLayer among other paremters.

      * HiddenServiceDescriptorV3, which contains the OuterLayer and plaintext
        parameters.

    Construction through this method can supply any or none of these, with
    omitted parameters populated with randomized defaults.

    Ed25519 key blinding adds an additional ~20 ms, and as such is disabled by
    default. To blind with a random nonce simply call...

    ::

      HiddenServiceDescriptorV3.create(blinding_nonce = os.urandom(32))

    :param dict attr: keyword/value mappings to be included in plaintext descriptor
    :param list exclude: mandatory keywords to exclude from the descriptor, this
      results in an invalid descriptor
    :param bool sign: includes cryptographic signatures and digests if True
    :param stem.descriptor.hidden_service.InnerLayer inner_layer: inner
      encrypted layer
    :param stem.descriptor.hidden_service.OuterLayer outer_layer: outer
      encrypted layer
    :param cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey
      identity_key: service identity key
    :param cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey
      signing_key: service signing key
    :param stem.descriptor.Ed25519CertificateV1 signing_cert: certificate
      signing this descriptor
    :param int revision_counter: descriptor revision number
    :param bytes blinding_nonce: 32 byte blinding factor to derive the blinding key

    :returns: **str** with the content of a descriptor

    :raises:
      * **ValueError** if parameters are malformed
      * **ImportError** if cryptography is unavailable
    TrO   zDHidden service descriptor creation requires cryptography version 2.6zoHidden service descriptor creation requires python 3.6+ or the pysha3 module (https://pypi.org/project/pysha3/)r3   z+Blinding nonce must be 32 bytes, but was %ir   rb   )r  s    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar   N)r  inner_layerr   r   r   )Z	cert_typer   rr   s@   bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)r!   3)r"   Z180r#   rz   ry   r$   r%   r   r;   s   signature %sr   )*rV   rW   rX   rY   _is_sha3_availabler}   rC   rf   rc   
InnerLayerr   rp   r   time_blinded_pubkeyrQ  _subcredentialr   
OuterLayerr   r   rq   r   r   ZHS_V3_DESC_SIGNING_blinded_signrt   r   r	   r   str_encryptrZ   rk   	_to_bytesri   rj   ZSIG_PREFIX_HS_V3rm   rn   r  r   )r  r  r  r  rR  outer_layeridentity_keyrU   r  r   blinding_noncerc   r   r   Z
custom_sigrr   Zdesc_contentZsig_contentr;   r;   r<   rD     sX   /

z!HiddenServiceDescriptorV3.contentTc                 C   s$   | |  ||||||||	|
|
|dS N)r   r  )r  r  r  r   r  rR  r^  r_  rU   r  r   r`  r;   r;   r<   r     s   $z HiddenServiceDescriptorV3.createc                    s   t t| j|| d d | _t||}|rntD ]}||vr#td| ||v r5t|| dkr5td| qdt|	 d krDtddt|	 d	 krRtd
| 
|| | jrjtjjddrl| j|  d S d S d S || _d S )Nr!  r"  r0   r#  r!   r   zAHidden service descriptor must start with a 'hs-descriptor' entryr   r   r$  TrO   )r%  rQ  r   _inner_layerr
   REQUIRED_V3_FIELDSrC   r}   r'  r   r(  r  rV   rW   rX   r   r+  )r   r,  r   r   r-  r.  r;   r<   r     s&   

z"HiddenServiceDescriptorV3.__init__c                 C   s   t jjddstdt j std| jdu rH| jr!| j nd}|s)tdt	
|}t	||}t| j| j||}t|| j||| _| jS )a   
    Decrypt this descriptor. Hidden serice descriptors contain two encryption
    layers (:class:`~stem.descriptor.hidden_service.OuterLayer` and
    :class:`~stem.descriptor.hidden_service.InnerLayer`).

    :param str onion_address: hidden service address this descriptor is from

    :returns: :class:`~stem.descriptor.hidden_service.InnerLayer` with our
      decrypted content

    :raises:
      * **ImportError** if required cryptography or sha3 module is unavailable
      * **ValueError** if unable to decrypt or validation fails
    TrO   zFHidden service descriptor decryption requires cryptography version 2.6zqHidden service descriptor decryption requires python 3.6+ or the pysha3 module (https://pypi.org/project/pysha3/)NzNo signing key is present)rV   rW   rX   rY   rT  rb  r  rU   rC   rQ  identity_key_from_addressrX  rY  _decryptr%   r   rU  )r   onion_addressr   Zidentity_public_keyr   r^  r;   r;   r<   decrypt(  s   


z!HiddenServiceDescriptorV3.decryptc                 C   s   t j s	tdt j| } t jjjj	
d}tt|  |  dd }t| | | }t jj|r=|d  S | S )a  
    Converts a hidden service identity key into its address. This accepts all
    key formats (private, public, or public bytes).

    :param Ed25519PublicKey,Ed25519PrivateKey,bytes key: hidden service identity key
    :param bool suffix: includes the '.onion' suffix if true, excluded otherwise

    :returns: **unicode** hidden service address

    :raises: **ImportError** if sha3 unsupported
    nHidden service address conversion requires python 3.6+ or the pysha3 module (https://pypi.org/project/pysha3/)r   Nr1   s   .onion)rV   rW   rT  rY   rZ   ro   r^   r_   r{   r|   rt   r   r   CHECKSUM_CONSTANTr   rm   Z	b32encoderk   rl   lower)r   suffixr   checksumrf  r;   r;   r<   address_from_identity_keyK  s   
$z3HiddenServiceDescriptorV3.address_from_identity_keyc                 C   s   t j s	td| dr| dd } t jjj| dds#td|  t	
|  }|dd }|dd	 }|d	d
 }tt| |  dd }||krkt jjt|}t jjt|}td||f |S )aB  
    Converts a hidden service address into its public identity key.

    :param str onion_address: hidden service address

    :returns: **bytes** for the hidden service's public identity key

    :raises:
      * **ImportError** if sha3 unsupported
      * **ValueError** if address malformed or checksum is invalid
    rh  z.onionNir   )r   z2'%s.onion' isn't a valid hidden service v3 addressr3   "   #   r1   z%Bad checksum (expected %s but was %s))rV   rW   rT  rY   r   rZ   Z	tor_toolsZis_valid_hidden_service_addressrC   rm   Z	b32decoder*  r   r   ri  r   rk   rl   r1  r2  )rf  Zdecoded_addressZpubkeyZexpected_checksumr   rl  Zchecksum_strZexpected_checksum_strr;   r;   r<   rd  d  s    

z3HiddenServiceDescriptorV3.identity_key_from_addressc                 C   s0   t dtj|   }t d||f  S )Ns   credential%ss   subcredential%s%s)r   r   rV   rZ   ro   r   )r_  r   Z
credentialr;   r;   r<   rX    s   z(HiddenServiceDescriptorV3._subcredential)
Nr;   FNNNNNNN)Nr;   TFNNNNNNNF)T)r7   r8   r9   r:   rF  _parse_v3_version_line_parse_lifetime_line_parse_signing_cert_parse_revision_counter_line_parse_superencrypted_line_parse_v3_signature_linerM  rN  rO  rD   r   r   rg  r   rm  rd  rX  rP  r;   r;   r.  r<   rQ    s:    
	_#
)rQ  c                       s~   e Zd ZdZdefdefi efdefdZeeeedZ	e
dd Zdd ZedddZedddZd fdd	Z  ZS )rY  a  
  Initial encryped layer of a hidden service v3 descriptor (`spec
  <https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt#n1154>`_).

  .. versionadded:: 1.8.0

  :var str auth_type: **\*** encryption scheme used for descriptor authorization
  :var str ephemeral_key: **\*** base64 encoded x25519 public key
  :var dict clients: **\*** mapping of authorized client ids to their
    :class:`~stem.descriptor.hidden_service.AuthorizedClient`
  :var str encrypted: **\*** encrypted descriptor inner layer

  **\*** attribute is either required when we're parsed with validation or has
  a default value, others are left as **None** if undefined
  N)r  r  r   r   )r  r  r   r   c                 C   s   t | d|||}t|S )N   hsdir-superencrypted-data)r   rY  )r   r   r   r   r   r;   r;   r<   re    s   zOuterLayer._decryptc                 C   s,   |   dt|   d   }t|d|||S )Nr=  i'  rw  )	get_bytesr}   r   )r   r   r   r   rD   r;   r;   r<   r\    s   zOuterLayer._encryptr;   TFc
                 C   s  t jjddstdt j std|rd|v rtdddlm}
 dd	lm	} |r.|nt
 }|r6|nd
}|	r<|	nt j|
 }	|rH|nt|
 |	}|shg }|r[d|v r[ntdD ]}|t  q_t||ddtt j| fgdd |D  dd||||	 ffS )NTrO   z?Hidden service layer creation requires cryptography version 2.6zjHidden service layer creation requires python 3.6+ or the pysha3 module (https://pypi.org/project/pysha3/)r   zOAuthorized clients cannot be specified through both attr and authorized_clientsr   rb   rd   r0   r2   )r  r   r  c                 S   s$   g | ]}d d|j |j|jf fqS )r   z%s %s %s)r   r   r   )ru   cr;   r;   r<   rw     s    z&OuterLayer.content.<locals>.<listcomp>r   r   )rV   rW   rX   rY   rT  rC   rf   rc   rg   re   rU  r   rZ   ro   rp   rQ  rX  r   r   r   r	   rm   rn   r\  )r  r  r  r   r  rR  r   authorized_clientsr   r   rc   re   r   r;   r;   r<   rD     s:   
zOuterLayer.contentc
           
      C   s"   | |  |||||||||		|dS ra  r  )
r  r  r  r   r  rR  r   rz  r   r   r;   r;   r<   r     s   "zOuterLayer.createc                    sR   t jj|d}tt| j|| d t||}|r$| 	|| d S || _
d S )Nr=  r!  )rV   rZ   rk   r]  r   r%  rY  r   r
   r(  r+  )r   rD   r   r   r.  r;   r<   r     s   

zOuterLayer.__init__)	Nr;   TFNNNNNrp  )r7   r8   r9   r:   _parse_v3_outer_auth_type_parse_v3_outer_ephemeral_keyr   _parse_v3_outer_encryptedrM  rN  r   re  r\  rO  rD   r   r   rP  r;   r;   r.  r<   rY    s(    

"rY  c                       s|   e Zd ZdZg efg efdefg efdZeeedZ	e
dd Zdd ZedddZedddZd fdd	Z  ZS )rU  aM  
  Second encryped layer of a hidden service v3 descriptor (`spec
  <https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt#n1308>`_).

  .. versionadded:: 1.8.0

  :var stem.descriptor.hidden_service.OuterLayer outer: enclosing encryption layer

  :var list formats: **\*** recognized CREATE2 cell formats
  :var list intro_auth: **\*** introduction-layer authentication types
  :var bool is_single_service: **\*** **True** if this is a `single onion service <https://gitweb.torproject.org/torspec.git/tree/proposals/260-rend-single-onion.txt>`_, **False** otherwise
  :var list introduction_points: :class:`~stem.descriptor.hidden_service.IntroductionPointV3` where this service is reachable

  **\*** attribute is either required when we're parsed with validation or has
  a default value, others are left as **None** if undefined
  F)r   r  r  r  )r   r  r  c                 C   s    t | jd|||}t|d| dS )N   hsdir-encrypted-dataT)r   r^  )r   r   rU  )r^  r   r   r   r   r;   r;   r<   re    s   zInnerLayer._decryptc                 C   s   t |  d|||S )Nr~  )r   rx  )r   r   r   r   r;   r;   r<   r\    s   zInnerLayer._encryptNr;   c                 C   s:   |rdd ttj| }nd}t||dtjj| S )Nrz   r  ))r   r  )	r~   mapr?   r   r	   rV   rZ   rk   r]  )r  r  r  r  r  rk  r;   r;   r<   rD   !  s   
zInnerLayer.contentTc                 C   s   | |  |||||dS ra  r  )r  r  r  r   r  r  r;   r;   r<   r   ,  s   zInnerLayer.createc                    s   t t| j|| d || _tjj|}|d}|dkr.||d d  | _	|d | }nd | _	t
||}|rE| || t| | d S || _d S )Nr!  r   r   r0   )r%  rU  r   ZouterrV   rZ   rk   r]  r  r   r
   r(  r  r+  )r   rD   r   r^  r  r   r.  r;   r<   r   0  s   


zInnerLayer.__init__)Nr;   FN)Nr;   TFN)FN)r7   r8   r9   r:   r   _parse_v3_inner_intro_auth_parse_v3_inner_single_servicer  rM  rN  r   re  r\  rO  rD   r   r   rP  r;   r;   r.  r<   rU    s&    

rU  c                    sb   ddl m djd  t fddtdjd D  }tj| }	
||S )Nr   rO   r1   c                 3   $    | ]}d |   | V  qdS r1   Nbitr;  r`  rP   r;   r<   	<genexpr>L     " z"_blinded_pubkey.<locals>.<genexpr>r   )	stem.utilrP   bsumr   ZdecodepointrV   rZ   ro   encodepoint
scalarmult)r_  r`  multPr;   r  r<   rW  I  s   2rW  c              	      s  ddl m} ddlm |j|jj|jj| d}	|dj
d  tfddtdj
d D  }d	fd
dtj
d j
d D }|| }dj
d  tfddtdj
d D  }	|d d }
|
|	 j }|dd  }	d| d d }||   d d }d	 fddtj
d j
d D |  }j|}||| |  |  j }|| S )Nr   )serializationrO   )encodingformatZencryption_algorithmr1   c                 3   s$    | ]}d |   | V  qdS r  r  r;  )rP   hr;   r<   r  ^  r  z _blinded_sign.<locals>.<genexpr>r   rs   c                       g | ]
} ||d   qS r0   r;   r;  )r  r;   r<   rw   _      z!_blinded_sign.<locals>.<listcomp>r   r:  c                 3   r  r  r  r;  r  r;   r<   r  d  r  r3   s'   Derive temporary signing key hash inputc                    r  r  r;   r;  )blinded_eskr;   r<   rw   n  r  )Zcryptography.hazmat.primitivesr  r  rP   Zprivate_bytesZEncodingZRawZPrivateFormatZNoEncryptionHr  r  r   r~   Z	encodeintZ	decodeintrv   ZHintr  Br  )msgr_  r   r`  r  Zidentity_key_bytesakZeskr  sZs_primeZk_primerRSr;   )r  r`  rP   r  r<   rZ  Q  s,   
2*24&rZ  r   )hr:   rm   r1  collectionsrh   r   r?  r   r   rV  Zstem.client.datatyperV   Zstem.descriptor.certificateZstem.prereqr  Zstem.util.connectionZstem.util.str_toolsZstem.util.tor_toolsr   r   r   r   r   Zstem.descriptorr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   rW   Z_is_lru_cache_available	functoolsr   Zstem.util.lru_cacheZ,cryptography.hazmat.backends.openssl.backendr   r   r   r   rY   r&  rc  rB  rD  r3  r5  ri  r   r   r   r   r   r5   
namedtupler   r>   r?   objectr   r   r   r   r   r   r   r   r   r  rH  rG  rI  rJ  rK  rL  rq  rr  Z_from_descriptorrs  rt  ru  rv  r{  r|  r}  r  r  r  r   rQ  rY  rU  rW  rZ  ZHiddenServiceDescriptorr;   r;   r;   r<   <module>   s   D


  
(







    aQ&