Hidden Service Descriptor
*************************

Parsing for Tor hidden service descriptors as described in Tor’s
version 2 and version 3 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
"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

New in version 1.4.0.

exception stem.descriptor.hidden_service.DecryptionFailure

   Bases: "Exception"

   Failure to decrypt the hidden service descriptor’s introduction-
   points.

class stem.descriptor.hidden_service.IntroductionPoints

   Bases: "stem.descriptor.hidden_service.IntroductionPoints"

   Introduction point for a v2 hidden service.

   Variables:
      * **identifier** (*str*) – hash of this introduction point’s
        identity key

      * **address** (*str*) – address of this introduction point

      * **port** (*int*) – port where this introduction point is
        listening

      * **onion_key** (*str*) – public key for communicating with
        this introduction point

      * **service_key** (*str*) – public key for communicating with
        this hidden service

      * **intro_authentication** (*list*) – tuples of the form
        (auth_type, auth_data) for establishing a connection

class stem.descriptor.hidden_service.IntroductionPointV3

   Bases: "stem.descriptor.hidden_service.IntroductionPointV3"

   Introduction point for a v3 hidden service.

   New in version 1.8.0.

   Variables:
      * **link_specifiers** (*list*) – "LinkSpecifier" where this
        service is reachable

      * **onion_key_raw** (*unicode*) – base64 ntor introduction
        point public key

      * **auth_key_cert**
        (*stem.descriptor.certificate.Ed25519Certificate*) – cross-
        certifier of the signing key with the auth key

      * **enc_key_raw** (*unicode*) – base64 introduction request
        encryption key

      * **enc_key_cert**
        (*stem.descriptor.certificate.Ed25519Certificate*) – cross-
        certifier of the signing key by the encryption key

      * **legacy_key_raw** (*str*) – base64 legacy introduction
        point RSA public key

      * **legacy_key_cert** (*str*) – base64 cross-certifier of the
        signing key by the legacy key

   static parse(content)

      Parses an introduction point from its descriptor content.

      Parameters:
         **content** (*str*) – descriptor content to parse

      Returns:
         "IntroductionPointV3" for the descriptor content

      Raises:
         **ValueError** if descriptor content is malformed

   static create_for_address(address, port, expiration=None, onion_key=None, enc_key=None, auth_key=None, signing_key=None)

      Simplified constructor for a single address/port link specifier.

      Parameters:
         * **address** (*str*) – IPv4 or IPv6 address where the
           service is reachable

         * **port** (*int*) – port where the service is reachable

         * **expiration** (*datetime.datetime*) – when certificates
           should expire

         * **onion_key** (*str*) – encoded, X25519PublicKey, or
           X25519PrivateKey onion key

         * **enc_key** (*str*) – encoded, X25519PublicKey, or
           X25519PrivateKey encryption key

         * **auth_key** (*str*) – encoded, Ed25519PublicKey, or
           Ed25519PrivateKey authentication key

         * **signing_key**
           (*cryptography.hazmat.primitives.asymmetri
           c.ed25519.Ed25519PrivateKey*) – service signing key

      Returns:
         "IntroductionPointV3" with these attributes

      Raises:
         **ValueError** if the address, port, or keys are malformed

   static create_for_link_specifiers(link_specifiers, expiration=None, onion_key=None, enc_key=None, auth_key=None, signing_key=None)

      Simplified constructor. For more sophisticated use cases you can
      use this as a template for how introduction points are properly
      created.

      Parameters:
         * **link_specifiers** (*list*) – series of
           stem.client.datatype.LinkSpecifier where the service is
           reachable

         * **expiration** (*datetime.datetime*) – when certificates
           should expire

         * **onion_key** (*str*) – encoded, X25519PublicKey, or
           X25519PrivateKey onion key

         * **enc_key** (*str*) – encoded, X25519PublicKey, or
           X25519PrivateKey encryption key

         * **auth_key** (*str*) – encoded, Ed25519PublicKey, or
           Ed25519PrivateKey authentication key

         * **signing_key**
           (*cryptography.hazmat.primitives.asymmetri
           c.ed25519.Ed25519PrivateKey*) – service signing key

      Returns:
         "IntroductionPointV3" with these attributes

      Raises:
         **ValueError** if the address, port, or keys are malformed

   encode()

      Descriptor representation of this introduction point.

      Returns:
         **str** for our descriptor representation

   onion_key()

      Provides our ntor introduction point public key.

      Returns:
         ntor "X25519PublicKey"

      Raises:
         * **ImportError** if required the cryptography module is
           unavailable

         * **EnvironmentError** if OpenSSL x25519 unsupported

   auth_key()

      Provides our authentication certificate’s public key.

      Returns:
         "Ed25519PublicKey"

      Raises:
         * **ImportError** if required the cryptography module is
           unavailable

         * **EnvironmentError** if OpenSSL x25519 unsupported

   enc_key()

      Provides our encryption key.

      Returns:
         encryption "X25519PublicKey"

      Raises:
         * **ImportError** if required the cryptography module is
           unavailable

         * **EnvironmentError** if OpenSSL x25519 unsupported

   legacy_key()

      Provides our legacy introduction point public key.

      Returns:
         legacy "X25519PublicKey"

      Raises:
         * **ImportError** if required the cryptography module is
           unavailable

         * **EnvironmentError** if OpenSSL x25519 unsupported

class stem.descriptor.hidden_service.AuthorizedClient(id=None, iv=None, cookie=None)

   Bases: "object"

   Client authorized to use a v3 hidden service.

   New in version 1.8.0.

   Variables:
      * **id** (*str*) – base64 encoded client id

      * **iv** (*str*) – base64 encoded randomized initialization
        vector

      * **cookie** (*str*) – base64 encoded authentication cookie

class stem.descriptor.hidden_service.BaseHiddenServiceDescriptor(contents, lazy_load=False)

   Bases: "stem.descriptor.Descriptor"

   Hidden service descriptor.

   New in version 1.8.0.

class stem.descriptor.hidden_service.HiddenServiceDescriptorV2(raw_contents, validate=False, skip_crypto_validation=False)

   Bases: "stem.descriptor.hidden_service.BaseHiddenServiceDescriptor"

   Version 2 hidden service descriptor.

   Variables:
      * **descriptor_id** (*str*) – ***** identifier for this
        descriptor, this is a base32 hash of several fields

      * **version** (*int*) – ***** hidden service descriptor
        version

      * **permanent_key** (*str*) – ***** long term key of the
        hidden service

      * **secret_id_part** (*str*) – ***** hash of the time period,
        cookie, and replica values so our descriptor_id can be
        validated

      * **published** (*datetime*) – ***** time in UTC when this
        descriptor was made

      * **protocol_versions** (*list*) – ***** list of **int**
        versions that are supported when establishing a connection

      * **introduction_points_encoded** (*str*) – raw introduction
        points blob

      * **introduction_points_auth** (*list*) – ***** tuples of the
        form (auth_method, auth_data) for our
        introduction_points_content (**deprecated**, always **[]**)

      * **introduction_points_content** (*bytes*) – decoded
        introduction-points content without authentication data, if
        using cookie authentication this is encrypted

      * **signature** (*str*) – 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

   Changed in version 1.6.0: Moved from the deprecated pycrypto module
   to cryptography for validating signatures.

   Changed in version 1.6.0: Added the **skip_crypto_validation**
   constructor argument.

   TYPE_ANNOTATION_NAME = 'hidden-service-descriptor'

   classmethod content(attr=None, exclude=(), sign=False)

      Creates descriptor content with the given attributes. Mandatory
      fields are filled with dummy information unless data is
      supplied. This doesn’t yet create a valid signature.

      New in version 1.6.0.

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in the descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

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

      Raises:
         * **ImportError** if cryptography is unavailable and sign
           is True

         * **NotImplementedError** if not implemented for this
           descriptor type

   classmethod create(attr=None, exclude=(), validate=True, sign=False)

      Creates a descriptor with the given attributes. Mandatory fields
      are filled with dummy information unless data is supplied. This
      doesn’t yet create a valid signature.

      New in version 1.6.0.

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in the descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **validate** (*bool*) – checks the validity of the
           descriptor’s content if **True**, skips these checks
           otherwise

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

      Returns:
         "Descriptor" subclass

      Raises:
         * **ValueError** if the contents is malformed and validate
           is True

         * **ImportError** if cryptography is unavailable and sign
           is True

         * **NotImplementedError** if not implemented for this
           descriptor type

   introduction_points

      Provided this service’s introduction points.

      Returns:
         **list** of "IntroductionPoints"

      Raises:
         * **ValueError** if the our introduction-points is
           malformed

         * **DecryptionFailure** if unable to decrypt this field

class stem.descriptor.hidden_service.HiddenServiceDescriptorV3(raw_contents, validate=False)

   Bases: "stem.descriptor.hidden_service.BaseHiddenServiceDescriptor"

   Version 3 hidden service descriptor.

   Variables:
      * **version** (*int*) – ***** hidden service descriptor
        version

      * **lifetime** (*int*) – ***** minutes after publication this
        descriptor is valid

      * **signing_cert**
        (*stem.descriptor.certificate.Ed25519Certificate*) – *****
        cross-certifier for the short-term descriptor signing key

      * **revision_counter** (*int*) – ***** descriptor revision
        number

      * **superencrypted** (*str*) – ***** encrypted HS-DESC-ENC
        payload

      * **signature** (*str*) – ***** 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

   New in version 1.8.0.

   TYPE_ANNOTATION_NAME = 'hidden-service-descriptor-3'

   classmethod content(attr=None, exclude=(), sign=False, inner_layer=None, outer_layer=None, identity_key=None, signing_key=None, signing_cert=None, revision_counter=None, blinding_nonce=None)

      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))

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in plaintext descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

         * **inner_layer**
           (*stem.descriptor.hidden_service.InnerLayer*) – inner
           encrypted layer

         * **outer_layer**
           (*stem.descriptor.hidden_service.OuterLayer*) – outer
           encrypted layer

      :param cryptography.hazmat.primitives.asymmetric.ed25519.Ed2551
      9PrivateKey
         identity_key: service identity key

      :param cryptography.hazmat.primitives.asymmetric.ed25519.Ed2551
      9PrivateKey
         signing_key: service signing key

      Parameters:
         * **signing_cert** (*stem.descriptor.Ed25519CertificateV1*)
           – certificate signing this descriptor

         * **revision_counter** (*int*) – descriptor revision number

         * **blinding_nonce** (*bytes*) – 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

   classmethod create(attr=None, exclude=(), validate=True, sign=False, inner_layer=None, outer_layer=None, identity_key=None, signing_key=None, signing_cert=None, revision_counter=None, blinding_nonce=None)

      Creates a descriptor with the given attributes. Mandatory fields
      are filled with dummy information unless data is supplied. This
      doesn’t yet create a valid signature.

      New in version 1.6.0.

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in the descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **validate** (*bool*) – checks the validity of the
           descriptor’s content if **True**, skips these checks
           otherwise

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

      Returns:
         "Descriptor" subclass

      Raises:
         * **ValueError** if the contents is malformed and validate
           is True

         * **ImportError** if cryptography is unavailable and sign
           is True

         * **NotImplementedError** if not implemented for this
           descriptor type

   decrypt(onion_address)

      Decrypt this descriptor. Hidden serice descriptors contain two
      encryption layers ("OuterLayer" and "InnerLayer").

      Parameters:
         **onion_address** (*str*) – hidden service address this
         descriptor is from

      Returns:
         "InnerLayer" with our decrypted content

      Raises:
         * **ImportError** if required cryptography or sha3 module
           is unavailable

         * **ValueError** if unable to decrypt or validation fails

   static address_from_identity_key(key, suffix=True)

      Converts a hidden service identity key into its address. This
      accepts all key formats (private, public, or public bytes).

      Parameters:
         * **key**
           (*Ed25519PublicKey**,**Ed25519PrivateKey**,**bytes*) –
           hidden service identity key

         * **suffix** (*bool*) – includes the ‘.onion’ suffix if
           true, excluded otherwise

      Returns:
         **unicode** hidden service address

      Raises:
         **ImportError** if sha3 unsupported

   static identity_key_from_address(onion_address)

      Converts a hidden service address into its public identity key.

      Parameters:
         **onion_address** (*str*) – 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

class stem.descriptor.hidden_service.OuterLayer(content, validate=False)

   Bases: "stem.descriptor.Descriptor"

   Initial encryped layer of a hidden service v3 descriptor (spec).

   New in version 1.8.0.

   Variables:
      * **auth_type** (*str*) – ***** encryption scheme used for
        descriptor authorization

      * **ephemeral_key** (*str*) – ***** base64 encoded x25519
        public key

      * **clients** (*dict*) – ***** mapping of authorized client
        ids to their "AuthorizedClient"

      * **encrypted** (*str*) – ***** 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

   classmethod content(attr=None, exclude=(), validate=True, sign=False, inner_layer=None, revision_counter=None, authorized_clients=None, subcredential=None, blinded_key=None)

      Creates descriptor content with the given attributes. Mandatory
      fields are filled with dummy information unless data is
      supplied. This doesn’t yet create a valid signature.

      New in version 1.6.0.

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in the descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

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

      Raises:
         * **ImportError** if cryptography is unavailable and sign
           is True

         * **NotImplementedError** if not implemented for this
           descriptor type

   classmethod create(attr=None, exclude=(), validate=True, sign=False, inner_layer=None, revision_counter=None, authorized_clients=None, subcredential=None, blinded_key=None)

      Creates a descriptor with the given attributes. Mandatory fields
      are filled with dummy information unless data is supplied. This
      doesn’t yet create a valid signature.

      New in version 1.6.0.

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in the descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **validate** (*bool*) – checks the validity of the
           descriptor’s content if **True**, skips these checks
           otherwise

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

      Returns:
         "Descriptor" subclass

      Raises:
         * **ValueError** if the contents is malformed and validate
           is True

         * **ImportError** if cryptography is unavailable and sign
           is True

         * **NotImplementedError** if not implemented for this
           descriptor type

class stem.descriptor.hidden_service.InnerLayer(content, validate=False, outer_layer=None)

   Bases: "stem.descriptor.Descriptor"

   Second encryped layer of a hidden service v3 descriptor (spec).

   New in version 1.8.0.

   Variables:
      * **outer** (*stem.descriptor.hidden_service.OuterLayer*) –
        enclosing encryption layer

      * **formats** (*list*) – ***** recognized CREATE2 cell formats

      * **intro_auth** (*list*) – ***** introduction-layer
        authentication types

      * **is_single_service** (*bool*) – ***** **True** if this is a
        single onion service, **False** otherwise

      * **introduction_points** (*list*) – "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

   classmethod content(attr=None, exclude=(), sign=False, introduction_points=None)

      Creates descriptor content with the given attributes. Mandatory
      fields are filled with dummy information unless data is
      supplied. This doesn’t yet create a valid signature.

      New in version 1.6.0.

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in the descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

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

      Raises:
         * **ImportError** if cryptography is unavailable and sign
           is True

         * **NotImplementedError** if not implemented for this
           descriptor type

   classmethod create(attr=None, exclude=(), validate=True, sign=False, introduction_points=None)

      Creates a descriptor with the given attributes. Mandatory fields
      are filled with dummy information unless data is supplied. This
      doesn’t yet create a valid signature.

      New in version 1.6.0.

      Parameters:
         * **attr** (*dict*) – keyword/value mappings to be included
           in the descriptor

         * **exclude** (*list*) – mandatory keywords to exclude from
           the descriptor, this results in an invalid descriptor

         * **validate** (*bool*) – checks the validity of the
           descriptor’s content if **True**, skips these checks
           otherwise

         * **sign** (*bool*) – includes cryptographic signatures and
           digests if True

      Returns:
         "Descriptor" subclass

      Raises:
         * **ValueError** if the contents is malformed and validate
           is True

         * **ImportError** if cryptography is unavailable and sign
           is True

         * **NotImplementedError** if not implemented for this
           descriptor type

stem.descriptor.hidden_service.HiddenServiceDescriptor

   alias of "stem.descriptor.hidden_service.HiddenServiceDescriptorV2"
