
    <iA                        S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	rSSK
rSSKrSSKrSSKJrJrJr  SSKJr  SrSrSrSrS	rS
r\R2                  R4                  R7                  SSSSSS5      r\R2                  R4                  R9                  S5      r\R2                  R4                  R7                  SS5      r " S S\5      r " S S\ 5      r! " S S\!5      r"g)ag
  
Parsing for `Tor Ed25519 certificates
<https://gitweb.torproject.org/torspec.git/tree/cert-spec.txt>`_, which are
used to for a variety of purposes...

  * validating the key used to sign server descriptors
  * validating the key used to sign hidden service v3 descriptors
  * signing and encrypting hidden service v3 indroductory points

.. versionadded:: 1.6.0

**Module Overview:**

::

  Ed25519Certificate - Ed25519 signing key certificate
    | +- Ed25519CertificateV1 - version 1 Ed25519 certificate
    |      |- is_expired - checks if certificate is presently expired
    |      |- signing_key - certificate signing key
    |      +- validate - validates a descriptor's signature
    |
    |- from_base64 - decodes a base64 encoded certificate
    |- to_base64 - base64 encoding of this certificate
    |
    |- unpack - decodes a byte encoded certificate
    +- pack - byte encoding of this certificate

  Ed25519Extension - extension included within an Ed25519Certificate

.. data:: CertType (enum)

  Purpose of Ed25519 certificate. For more information see...

    * `cert-spec.txt <https://gitweb.torproject.org/torspec.git/tree/cert-spec.txt>`_ section A.1
    * `rend-spec-v3.txt <https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt>`_ appendix E

  .. deprecated:: 1.8.0
     Replaced with :data:`stem.client.datatype.CertType`

  ========================  ===========
  CertType                  Description
  ========================  ===========
  **SIGNING**               signing key with an identity key
  **LINK_CERT**             TLS link certificate signed with ed25519 signing key
  **AUTH**                  authentication key signed with ed25519 signing key
  **HS_V3_DESC_SIGNING**    hidden service v3 short-term descriptor signing key
  **HS_V3_INTRO_AUTH**      hidden service v3 introductory point authentication key
  **HS_V3_INTRO_ENCRYPT**   hidden service v3 introductory point encryption key
  ========================  ===========

.. data:: ExtensionType (enum)

  Recognized exception types.

  ====================  ===========
  ExtensionType         Description
  ====================  ===========
  **HAS_SIGNING_KEY**   includes key used to sign the certificate
  ====================  ===========

.. data:: ExtensionFlag (enum)

  Flags that can be assigned to Ed25519 certificate extensions.

  ======================  ===========
  ExtensionFlag           Description
  ======================  ===========
  **AFFECTS_VALIDATION**  extension affects whether the certificate is valid
  **UNKNOWN**             extension includes flags not yet recognized by stem
  ======================  ===========
    N)FieldSizesplit)CertType    (   @   s"   Tor router descriptor signature v1s#   Tor onion service descriptor sig v36   SIGNING	LINK_CERTAUTHHS_V3_DESC_SIGNINGHS_V3_INTRO_AUTHHS_V3_INTRO_ENCRYPT)HAS_SIGNING_KEY   AFFECTS_VALIDATIONUNKNOWNc                   :    \ rS rSrSrS rS r\S 5       rS r	Sr
g)	Ed25519Extensionv   a  
Extension within an Ed25519 certificate.

:var stem.descriptor.certificate.ExtensionType type: extension type
:var list flags: extension attribute flags
:var int flag_int: integer encoding of the extension attribute flags
:var bytes data: data the extension concerns
c                    Xl         / U l        U(       a  UOSU l        X0l        U(       a7  US-  S:X  a.  U R                  R	                  [
        R                  5        US-  nU(       a)  U R                  R	                  [
        R                  5        U[        R                  :X  a'  [        U5      S:w  a  [        S[        U5      -  5      eg g )Nr         r   z?Ed25519 HAS_SIGNING_KEY extension must be 32 bytes, but was %i.)typeflagsflag_intdataappendExtensionFlagr   r   ExtensionTyper   len
ValueError)selfext_typeflag_valr   s       U/home/james-whalen/.local/lib/python3.13/site-packages/stem/descriptor/certificate.py__init__Ed25519Extension.__init__   s    IDJ (HaDMIHqLA%
jj889!mh
jj--.=000SY"_X[^_c[ddee 6E0    c                 b   [        5       nU[        R                  R                  [	        U R
                  5      5      -  nU[        R                  R                  U R                  5      -  nU[        R                  R                  U R                  5      -  nXR
                  -  n[        U5      $ N)
	bytearrayr   SHORTpackr"   r   CHARr   r   bytes)r$   encodeds     r'   r/   Ed25519Extension.pack   st    kGtzzs499~..Gtyy~~dii((Gtyy~~dmm,,GyyG>r*   c                    [        U 5      S:  a  [        S5      e[        R                  R	                  U 5      u  p[        R
                  R	                  U 5      u  p [        R
                  R	                  U 5      u  p0[        X5      u  p@[        U5      U:w  a  [        SU[        U5      4-  5      e[        X#U5      U 4$ )Nr   z*Ed25519 extension is missing header fieldszTEd25519 extension is truncated. It should have %i bytes of data but there's only %i.)r"   r#   r   r.   popr0   r   r   )content	data_sizer%   r   r   s        r'   r5   Ed25519Extension.pop   s    
7|aCDD0I		g.HYY]]7+NE'-MD
4yImqz|  AE  }F  qG  G  H  HHT2G;;r*   c                 D    [         R                  R                  U SSSSS9$ )Nr   r   r   T)cache)stemutil
_hash_attrr$   s    r'   __hash__Ed25519Extension.__hash__   s"    99fj&$OOr*   )r   r   r   r   N)__name__
__module____qualname____firstlineno____doc__r(   r/   staticmethodr5   r?   __static_attributes__ r*   r'   r   r   v   s,    f  < <Pr*   r   c                   t    \ rS rSrSrS r\S 5       r\S 5       rS r	SS jr
\S 5       rS	 r\S
 5       rSrg)Ed25519Certificate   z
Base class for an Ed25519 certificate.

:var int version: certificate format version
:var unicode encoded: base64 encoded ed25519 certificate
c                     Xl         S U l        g r,   )versionr2   )r$   rM   s     r'   r(   Ed25519Certificate.__init__   s    LDLr*   c                     [         R                  R                  U 5      S   nUS:X  a  [        R	                  U 5      $ [        SU-  5      e)z
Parses a byte encoded ED25519 certificate.

:param bytes content: encoded certificate

:returns: :class:`~stem.descriptor.certificate.Ed25519Certificate` subclsss
  for the given certificate

:raises: **ValueError** if certificate is malformed
r   r   zLEd25519 certificate is version %i. Parser presently only supports version 1.)r   r0   r5   Ed25519CertificateV1unpackr#   )r6   rM   s     r'   rQ   Ed25519Certificate.unpack   sE     iimmG$Q'G!|!((11ehooppr*   c                    [         R                  R                  R                  U 5      n U R	                  S5      (       a  U R                  S5      (       a  U SS n  [        R                  " U 5      nU(       d  [        S5      e[        R                  U5      nXl        U$ ! [        [        R                  4 a  n[        SU< SU < 35      eSnAff = f)	z
Parses a base64 encoded ED25519 certificate.

:param str content: base64 encoded certificate

:returns: :class:`~stem.descriptor.certificate.Ed25519Certificate` subclsss
  for the given certificate

:raises: **ValueError** if content is malformed
z-----BEGIN ED25519 CERT-----
z
-----END ED25519 CERT-----   iemptyz5Ed25519 certificate wasn't propoerly base64 encoded (z):
N)r;   r<   	str_tools_to_unicode
startswithendswithbase64	b64decode	TypeErrorrJ   rQ   r2   binasciiErrorr#   )r6   decodedinstanceexcs       r'   from_base64Ed25519Certificate.from_base64   s     ii!!--g6G:;;@P@PQo@p@p3g
i  )g  #**73h ox~~& iZ]_fghhis   AB! !C;CCc                 D    [        S[        U 5      R                  -  5      e)zq
Encoded byte representation of our certificate.

:returns: **bytes** for our encoded certificate representation
z4Certificate encoding has not been implemented for %s)NotImplementedErrorr   rA   r>   s    r'   r/   Ed25519Certificate.pack   s"     TW[\`WaWjWjj
kkr*   c                 "   SR                  [        R                  R                  R	                  [
        R                  " U R                  5       5      S5      5      nU(       a  SU-  n[        R                  R                  R                  U5      $ )a  
Base64 encoded certificate data.

:param bool pem: include `PEM header/footer
  <https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail>`_, for more
  information see `RFC 7468 <https://tools.ietf.org/html/rfc7468>`_

:returns: **unicode** for our encoded certificate representation
   
r	   s:   -----BEGIN ED25519 CERT-----
%s
-----END ED25519 CERT-----)	joinr;   r<   rV   _split_by_lengthrZ   	b64encoder/   rW   )r$   pemr2   s      r'   	to_base64Ed25519Certificate.to_base64   sd     jj,,==f>N>Ntyy{>[]_`aG
ORYYg99**733r*   c                    ^ ^ UU 4S jnU$ )Nc                    > UT   S   u  p#nU(       a  US:w  a  [        ST< SU< 35      e[        U T[        R                  U5      5        g )Nr   zED25519 CERT'z8' should be followed by a ED25519 CERT block, but was a )r#   setattrrJ   rb   )
descriptorentriesvalue
block_typeblock_contents	attributekeywords        r'   _parse3Ed25519Certificate._from_descriptor.<locals>._parse  sK    *1'*:1*='ez^;\ceopqqj)%7%C%CN%STr*   rH   )ry   rx   rz   s   `` r'   _from_descriptor#Ed25519Certificate._from_descriptor  s    U Mr*   c                      U R                  SS9$ )NT)rl   )rm   r>   s    r'   __str__Ed25519Certificate.__str__  s    >>>%%r*   c                 ,    [         R                  U 5      $ r,   )rJ   rb   )r6   s    r'   parseEd25519Certificate.parse  s    ))'22r*   )r2   rM   N)F)rA   rB   rC   rD   rE   r(   rF   rQ   rb   r/   rm   r|   r   r   rG   rH   r*   r'   rJ   rJ      sp     q q& i i:l4$ 	 	& 3 3r*   rJ   c                   n   ^  \ rS rSrSrSU 4S jjrS r\S 5       rS r	S r
S r\S	 5       rS
 rSrU =r$ )rP   i  a  
Version 1 Ed25519 certificate, which are used for signing tor server
descriptors.

:var stem.client.datatype.CertType type: certificate purpose
:var int type_int: integer value of the certificate purpose
:var datetime expiration: expiration of the certificate
:var int key_type: format of the key
:var bytes key: key content
:var list extensions: :class:`~stem.descriptor.certificate.Ed25519Extension` in this certificate
:var bytes signature: certificate signature

:param bytes signature: pre-calculated certificate signature
:param cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey signing_key: certificate signing key
c                   > [         [        U ]  S5        Uc  [        S5      eUc  [        S5      e[        R
                  " U5      u  U l        U l        U(       a  UO6[        R                  R                  5       [        R                  " [        S9-   U l        U(       a  UOSU l        [        R                  R!                  U5      U l        U(       a  UO/ U l        X`l        U(       ad  UR)                  U R+                  5       5      nU R&                  (       a.  U R&                  U:w  a  [        SU< SU R&                  < S35      eXl        U R                  [        R,                  [        R.                  [        R0                  4;   a  [        SU R                  -  5      eU R                  [        R2                  :X  a  [        S	5      eU R                  [        R4                  :X  a  [        S
U R                  -  5      eg )Nr   zCertificate type is requiredzCertificate key is required)hoursz#Signature calculated from its key (z) mismatches 'rq   zOEd25519 certificate cannot have a type of %i. This is reserved for CERTS cells.zcEd25519 certificate cannot have a type of 7. This is reserved for RSA identity cross-certification.z+Ed25519 certificate type %i is unrecognized)superrP   r(   r#   ClientCertTypegetr   type_intdatetimeutcnow	timedeltaDEFAULT_EXPIRATION_HOURS
expirationkey_typer;   r<   _pubkey_byteskey
extensions	signaturesignr/   LINKIDENTITYAUTHENTICATEED25519_IDENTITYr   )
r$   	cert_typer   r   r   r   r   signing_keycalculated_sig	__class__s
            r'   r(   Ed25519CertificateV1.__init__)  s   	
.q1566	455-11)<DIt}$.jH4E4E4L4L4NQYQcQc  mE  RF  5FDO (HaDMyy&&s+DH$.jBDON"''		4n 
DNNn<Uceiesestuu%nyy^((.*A*A>C^C^__hkokxkxxyy	n55	5|}}	n,,	,Dt}}TUU 
-r*   c                    [        5       nU[        R                  R                  U R                  5      -  nU[        R                  R                  U R
                  5      -  nU[        R                  R                  [        [        R                  R                  U R                  5      S-  5      5      -  nU[        R                  R                  U R                  5      -  nXR                  -  nU[        R                  R                  [        U R                  5      5      -  nU R                   H  nXR                  5       -  nM     U R                   (       a  XR                   -  n[#        U5      $ )N  )r-   r   r0   r/   rM   r   LONGintr;   r<   datetime_to_unixr   r   r   r"   r   r   r1   )r$   r2   	extensions      r'   r/   Ed25519CertificateV1.packI  s    kGtyy~~dll++Gtyy~~dmm,,Gtyy~~c$))"<"<T__"MPT"TUVVGtyy~~dmm,,GxxGtyy~~c$//233G__	!!g % ~~g>r*   c                 `   [        U 5      [        [        -   :  a$  [        S[        U 5      [        [        -   4-  5      e[	        U [        U 5      [        -
  5      u  p[
        R                  R                  U5      u  p1[
        R                  R                  U5      u  pA[
        R                  R                  U5      u  pQ[
        R                  R                  U5      u  pa[	        U[        5      u  pq[
        R                  R                  U5      u  pUS:w  a  [        SU-  5      e/ n
[        U5       H+  n[        R                  U	5      u  pU
R                  U5        M-     U	(       a  [        S[        U	5      -  5      e[        U[        R                  R                  US-  5      XgX5      $ )Nz;Ed25519 certificate was %i bytes, but should be at least %ir   z5Ed25519 v1 parser cannot read version %i certificatesz9Ed25519 certificate had %i bytes of unused extension datar   )r"   ED25519_HEADER_LENGTHED25519_SIGNATURE_LENGTHr#   r   r   r0   r5   r   ED25519_KEY_LENGTHranger   r   rP   r   utcfromtimestamp)r6   headerr   rM   r   expiration_hoursr   r   extension_countextension_datar   ir   s                r'   rQ   Ed25519CertificateV1.unpackZ  s   
7|+.FFFTX[\cXdf{  W  gW  XX  X  Y  Ygs7|6N'NOFiimmF+OG		f-I#yy}}V4yy}}V,H 23KC&*iimmF&;#O!|NQXXYYJ?#"2"6"6~"Fi	" $ RUXYgUhhii	8+<+<+M+MN^aeNe+fhp  xB  N  Nr*   c                 X    [         R                   R                  5       U R                  :  $ )z
Checks if this certificate is presently expired or not.

:returns: **True** if the certificate has expired, **False** otherwise
)r   nowr   r>   s    r'   
is_expiredEd25519CertificateV1.is_expiredv  s"       "T__44r*   c                     U R                    H/  nUR                  [        R                  :X  d  M#  UR                  s  $    g)z
Provides this certificate's signing key.

.. versionadded:: 1.8.0

:returns: **bytes** with the first signing key on the certificate, None if
  not present
N)r   r   r!   r   r   )r$   r   s     r'   r    Ed25519CertificateV1.signing_key  s3     __		=88	8~~ % r*   c                    [         R                  R                  SS9(       d  [        S5      e[	        U[         R
                  R                  R                  5      (       a|  [        R                  " [        R                  U5      5      R                  5       n[         R                  R                  R                  UR                   5      nU R#                  U5        O[	        U[         R
                  R$                  R&                  5      (       aI  [        R                  U5      n[         R                  R                  R                  UR(                  5      nO![+        S[-        U5      R.                  -  5      eSSKJn  SSKJn   UR9                  U R:                  5      nUR=                  X25        g	! U a    [?        S5      ef = f)
a  
Validate our descriptor content matches its ed25519 signature. Supported
descriptor types include...

  * :class:`~stem.descriptor.server_descriptor.RelayDescriptor`
  * :class:`~stem.descriptor.hidden_service.HiddenServiceDescriptorV3`

:param stem.descriptor.__init__.Descriptor descriptor: descriptor to validate

:raises:
  * **ValueError** if signing key or descriptor are invalid
  * **TypeError** if descriptor type is unsupported
  * **ImportError** if cryptography module or ed25519 support unavailable
T)ed25519zKCertificate validation requires the cryptography module and ed25519 supportzWCertificate validation only supported for server and hidden service descriptors, not %sr   Ed25519PublicKeyInvalidSignaturezNDescriptor Ed25519 certificate signature invalid (signature forged or corrupt)N) r;   prereqis_crypto_availableImportError
isinstancers   server_descriptorRelayDescriptorhashlibsha256rP   _signed_contentdigestr<   rV   _decode_b64ed25519_signature!_validate_server_desc_signing_keyhidden_serviceHiddenServiceDescriptorV3r   r\   r   rA   1cryptography.hazmat.primitives.asymmetric.ed25519r   cryptography.exceptionsr   from_public_bytesr   verifyr#   )r$   rs   signed_contentr   r   r   r   s          r'   validateEd25519CertificateV1.validate  s`     ;;**T*:eff*doo??OOPP~~&:&J&J:&VW^^`n))%%11*2N2NOi
,,Z8	J > > X X	Y	Y+;;JGn))%%11*2F2FGiorv  xB  sC  sL  sL  L  M  MR8i..txx8c	jj+ ighhis   ,F4 4Gc                    [        U [        R                  R                  R                  5      (       a	  [
        nSnO][        U [        R                  R                  R                  5      (       a	  [        nSnO![        S[        U 5      R                  -  5      e[        R                  " X R                  5       [        R                  5      nU(       d  [        S5      eXR!                  S5      -   $ )zi
Provides this descriptor's signing constant, appended with the portion of
the descriptor that's signed.
s   (.+router-sig-ed25519 )s   (.+)signature zBUG: %s type unexpectedz+Malformed descriptor missing signature liner   )r   r;   rs   r   r   SIG_PREFIX_SERVER_DESCr   r   SIG_PREFIX_HS_V3r#   r   rA   research	get_bytesDOTALLgroup)rs   prefixregexmatchs       r'   r   $Ed25519CertificateV1._signed_content  s     *doo??OOPP%f(e	J > > X X	Y	Yfe04
3C3L3LLMMIIe113RYY?EDEEKKN""r*   c                 8   SSK Jn  SSKJn  UR                  (       aK  [
        R                  " [        R                  R                  R                  UR                  5      S-   5      nOU R                  5       nU(       d  [        S5      e UR                  U5      nUR                  U R                  [
        R                  " [        R                  R                  R                  U R                   5      5      S ["        *  5        g ! U a    [        S5      ef = f)Nr   r   r      =z0Server descriptor missing an ed25519 signing keyzJEd25519KeyCertificate signing key is invalid (signature forged or corrupt))r   r   r   r   ed25519_master_keyrZ   r[   r;   r<   rV   	_to_bytesr   r#   r   r   r   r2   r   )r$   rs   r   r   r   r   s         r'   r   6Ed25519CertificateV1._validate_server_desc_signing_key  s    R8$$$$TYY%8%8%B%B:C`C`%adh%hik$$&kIJJe..{;c	jj!1!1$))2E2E2O2OPTP\P\2]!^_yay`y!z{ ecddes   A:D D)r   r   r   r   r   r   r   )NNNNNNN)rA   rB   rC   rD   rE   r(   r/   rF   rQ   r   r   r   r   r   rG   __classcell__)r   s   @r'   rP   rP     s[     V@" N N65 %iN # #,e er*   rP   )#rE   rZ   r]   r   r   r   stem.descriptor.hidden_servicer;   !stem.descriptor.server_descriptorstem.prereq	stem.utilstem.util.enumstem.util.str_toolsstem.client.datatyper   r   r   r   r   r   r   r   r   r   r   r<   enumUppercaseEnumEnumr!   r    r   objectrJ   rP   rH   r*   r'   <module>r      s   FP     	 % (     3 3
 <   > 9  99>>'' 		##$:<		,,-A9M2Pu 2Pjj3 j3ZEe- Eer*   