o
    ¯bV ã                   @   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mZmZm	Z	 ddl
mZm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 dd	lmZmZmZmZmZ dd
lmZmZm Z  ddl!m"Z"m#Z# ddl$m%Z&m'Z( ddl)m*Z* ddl+m,Z, ddl-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3 ddl4m5Z5m6Z6 ddl7m8Z8m9Z9 ddl:m;Z; z
ddl<m=Z=m>Z> W n e?y¿   ddl<m@Z=mAZ> Y nw e B¡ e C¡ e D¡ dœZEddddœZFG dd„ deGƒZHG dd„ deGƒZIG d d!„ d!eGƒZJG d"d#„ d#e9ƒZKG d$d%„ d%eGƒZLd&d'„ ZMG d(d)„ d)ƒZNd-d+d,„ZOdS ).z0
Handling of RSA, DSA, ECDSA, and Ed25519 keys.
é    N)Ú	b64encodeÚdecodebytesÚencodebytes)Úmd5Úsha256)Úutils)ÚInvalidSignature)Údefault_backend)ÚhashesÚserialization)ÚdsaÚecÚed25519ÚpaddingÚrsa)ÚCipherÚ
algorithmsÚmodes)Úload_pem_private_keyÚload_ssh_public_key)ÚdecoderÚencoder)ÚPyAsn1Error)Úuniv)ÚcommonÚsexpy)Úint_to_bytes)Ú	randbytes)Ú	iterbytesÚnativeString)ÚNamedConstantÚNames)Ú_mutuallyExclusiveArguments)Údecode_dss_signatureÚencode_dss_signature)Údecode_rfc6979_signatureÚencode_rfc6979_signature)s   ecdsa-sha2-nistp256s   ecdsa-sha2-nistp384s   ecdsa-sha2-nistp521s   nistp256s   nistp384s   nistp521)s	   secp256r1s	   secp384r1s	   secp521r1c                   @   ó   e Zd ZdZdS )ÚBadKeyErrorzj
    Raised when a key isn't what we expected from it.

    XXX: we really need to check for bad keys
    N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r.   r.   ú8/usr/lib/python3/dist-packages/twisted/conch/ssh/keys.pyr(   F   ó    r(   c                   @   r'   )ÚEncryptedKeyErrorzb
    Raised when an encrypted key is presented to fromString/fromFile without
    a password.
    Nr)   r.   r.   r.   r/   r1   N   r0   r1   c                   @   r'   )ÚBadFingerPrintFormatzS
    Raises when unsupported fingerprint formats are presented to fingerprint.
    Nr)   r.   r.   r.   r/   r2   U   r0   r2   c                   @   s   e Zd ZdZeƒ Zeƒ ZdS )ÚFingerprintFormatsaä  
    Constants representing the supported formats of key fingerprints.

    @cvar MD5_HEX: Named constant representing fingerprint format generated
        using md5[RFC1321] algorithm in hexadecimal encoding.
    @type MD5_HEX: L{twisted.python.constants.NamedConstant}

    @cvar SHA256_BASE64: Named constant representing fingerprint format
        generated using sha256[RFC4634] algorithm in base64 encoding
    @type SHA256_BASE64: L{twisted.python.constants.NamedConstant}
    N)r*   r+   r,   r-   r    ÚMD5_HEXÚSHA256_BASE64r.   r.   r.   r/   r3   [   s    
r3   c                   @   r'   )ÚPassphraseNormalizationErrorzŒ
    Raised when a passphrase contains Unicode characters that cannot be
    normalized using the available Unicode character database.
    Nr)   r.   r.   r.   r/   r6   l   r0   r6   c                 C   s8   t | tƒrtdd„ | D ƒƒrtƒ ‚t d| ¡ d¡S | S )aî  
    Normalize a passphrase, which may be Unicode.

    If the passphrase is Unicode, this follows the requirements of U{NIST
    800-63B, section
    5.1.1.2<https://pages.nist.gov/800-63-3/sp800-63b.html#memsecretver>}
    for Unicode characters in memorized secrets: it applies the
    Normalization Process for Stabilized Strings using NFKC normalization.
    The passphrase is then encoded using UTF-8.

    @type passphrase: L{bytes} or L{unicode} or L{None}
    @param passphrase: The passphrase to normalize.

    @return: The normalized passphrase, if any.
    @rtype: L{bytes} or L{None}
    @raises PassphraseNormalizationError: if the passphrase is Unicode and
    cannot be normalized using the available Unicode character database.
    c                 s   s   � | ]
}t  |¡d kV  qdS )ÚCnN)ÚunicodedataÚcategory)Ú.0Úcr.   r.   r/   Ú	<genexpr>‰   s   € z'_normalizePassphrase.<locals>.<genexpr>ÚNFKCzUTF-8)Ú
isinstanceÚstrÚanyr6   r8   Ú	normalizeÚencode©Ú
passphraser.   r.   r/   Ú_normalizePassphrases   s
   
rE   c                   @   sÆ  e Zd ZdZedTdd„ƒZedTdd„ƒZedd„ ƒZed	d
„ ƒZedd„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedUdd„ƒZedVdd„ƒZedVdd „ƒZedVd!d"„ƒZedVd#d$„ƒZd%d&„ Zd'ed(efd)d*„Zd(efd+d,„Zd-d.„ Zd/d0„ Zejfd1d2„Z d3d4„ Z!d5d6„ Z"d7d8„ Z#d9d:„ Z$d;d<„ Z%d=d>„ Z&e'd?d@gd?dAggƒdUdBdC„ƒZ(dVdDdE„Z)dTdFdG„Z*dVdHdI„Z+dWdJdK„Z,dLdM„ Z-dNdO„ Z.dPdQ„ Z/dRdS„ Z0dS )XÚKeyau  
    An object representing a key.  A key can be either a public or
    private key.  A public key can verify a signature; a private key can
    create or verify a signature.  To generate a string that can be stored
    on disk, use the toString method.  If you have a private key, but want
    the string representation of the public key, use Key.public().toString().
    Nc                 C   s@   t |dƒ�}|  | ¡ ||¡W  d  ƒ S 1 sw   Y  dS )aâ  
        Load a key from a file.

        @param filename: The path to load key data from.

        @type type: L{str} or L{None}
        @param type: A string describing the format the key data is in, or
        L{None} to attempt detection of the type.

        @type passphrase: L{bytes} or L{None}
        @param passphrase: The passphrase the key is encrypted with, or L{None}
        if there is no encryption.

        @rtype: L{Key}
        @return: The loaded key.
        ÚrbN)ÚopenÚ
fromStringÚread)ÚclsÚfilenameÚtyperD   Úfr.   r.   r/   ÚfromFile›   s   $ÿzKey.fromFilec                 C   sš   t |tƒr
| d¡}t|ƒ}|du r|  |¡}|du r"td|›�ƒ‚t| d| ¡ › �dƒ}|du r8td|› �ƒ‚|jj	dkrH|rDtdƒ‚||ƒS |||ƒS )a   
        Return a Key object corresponding to the string data.
        type is optionally the type of string, matching a _fromString_*
        method.  Otherwise, the _guessStringType() classmethod will be used
        to guess a type.  If the key is encrypted, passphrase is used as
        the decryption key.

        @type data: L{bytes}
        @param data: The key data.

        @type type: L{str} or L{None}
        @param type: A string describing the format the key data is in, or
        L{None} to attempt detection of the type.

        @type passphrase: L{bytes} or L{None}
        @param passphrase: The passphrase the key is encrypted with, or L{None}
        if there is no encryption.

        @rtype: L{Key}
        @return: The loaded key.
        úutf-8Nzcannot guess the type of Ú_fromString_zno _fromString method for é   zkey not encrypted)
r>   r?   rB   rE   Ú_guessStringTyper(   ÚgetattrÚupperÚ__code__Úco_argcount)rK   ÚdatarM   rD   Úmethodr.   r.   r/   rI   °   s   



zKey.fromStringc                 C   sÜ   t  |¡\}}|dkr t  |d¡\}}}| t ||¡ tƒ ¡ƒS |dkrBt  |d¡\}}}}	}| tj|	tj	|||d�d� tƒ ¡ƒS |t
v rW| tj t
| t  |d¡d ¡ƒS |dkrgt  |¡\}
}|  |
¡S td	|› �ƒ‚)
a„  
        Return a public key object corresponding to this public key blob.
        The format of a RSA public key blob is::
            string 'ssh-rsa'
            integer e
            integer n

        The format of a DSA public key blob is::
            string 'ssh-dss'
            integer p
            integer q
            integer g
            integer y

        The format of ECDSA-SHA2-* public key blob is::
            string 'ecdsa-sha2-[identifier]'
            integer x
            integer y

            identifier is the standard NIST curve name.

        The format of an Ed25519 public key blob is::
            string 'ssh-ed25519'
            string a

        @type blob: L{bytes}
        @param blob: The key data.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if the key type (the first string) is unknown.
        ó   ssh-rsarR   ó   ssh-dssé   ©ÚpÚqÚg©ÚyÚparameter_numbersé   ó   ssh-ed25519úunknown blob type: )r   ÚgetNSÚgetMPr   ÚRSAPublicNumbersÚ
public_keyr	   r   ÚDSAPublicNumbersÚDSAParameterNumbersÚ_curveTabler   ÚEllipticCurvePublicKeyÚfrom_encoded_pointÚ_fromEd25519Componentsr(   )rK   ÚblobÚkeyTypeÚrestÚeÚnr^   r_   r`   rb   Úar.   r.   r/   Ú_fromString_BLOBØ   s,   "ÿýÿÿ
zKey._fromString_BLOBc                 C   s  t  |¡\}}|dkr"t  |d¡\}}}}}}	}| j|||||	d�S |dkr<t  |d¡\}}	}
}}}| j||
||	|d�S |tv rnt| }t  |d¡\}}	}|t|j d¡ kr_t	d	||f ƒ‚t  |¡\}}| j
|	||d
�S |dkrˆt  |d¡\}}}|dd… }| j||d�S t	d|› �ƒ‚)a6  
        Return a private key object corresponding to this private key blob.
        The blob formats are as follows:

        RSA keys::
            string 'ssh-rsa'
            integer n
            integer e
            integer d
            integer u
            integer p
            integer q

        DSA keys::
            string 'ssh-dss'
            integer p
            integer q
            integer g
            integer y
            integer x

        EC keys::
            string 'ecdsa-sha2-[identifier]'
            string identifier
            string q
            integer privateValue

            identifier is the standard NIST curve name.

        Ed25519 keys::
            string 'ssh-ed25519'
            string a
            string k || a


        @type blob: L{bytes}
        @param blob: The key data.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if
            * the key type (the first string) is unknown
            * the curve name of an ECDSA key does not match the key type
        rZ   é   ©ru   rt   Údr^   r_   r[   é   ©rb   r`   r^   r_   ÚxrR   Úasciiz.ECDSA curve name %r does not match key type %r)ÚencodedPointÚcurveÚprivateValuere   Né    )Úkrf   )r   rg   rh   Ú_fromRSAComponentsÚ_fromDSAComponentsrm   Ú
_secToNistÚnamerB   r(   Ú_fromECEncodedPointrp   )rK   rq   rr   rs   ru   rt   rz   Úur^   r_   r`   rb   r}   r€   Ú	curveNamer�   rv   Úcombinedrƒ   r.   r.   r/   Ú_fromString_PRIVATE_BLOB  s2   .ÿÿÿzKey._fromString_PRIVATE_BLOBc                 C   s4   |  d¡r| t|tƒ ƒƒS t| ¡ d ƒ}|  |¡S )a”  
        Return a public key object corresponding to this OpenSSH public key
        string.  The format of an OpenSSH public key string is::
            <key type> <base64-encoded public key blob>

        @type data: L{bytes}
        @param data: The key data.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if the blob type is unknown.
        s
   ecdsa-sha2rd   )Ú
startswithr   r	   r   Úsplitrw   )rK   rX   rq   r.   r.   r/   Ú_fromString_PUBLIC_OPENSSH\  s   

zKey._fromString_PUBLIC_OPENSSHc                 C   s  |  ¡  ¡ }td |dd… ¡ƒ}| d¡stdƒ‚|tdƒd… }t |d¡\}}}}t	 
d|dd	… ¡d
 }	|	dkr@tdƒ‚t |d	d… d¡\}
}}
|dkrÎ|sWtdƒ‚|dv rmtj}d}t|dd… ƒd }|}ntd|›�ƒ‚|dkr˜t |¡\}}t	 
d|dd	… ¡d
 }tj|||| |dd�}ntd|›�ƒ‚t|ƒ| d
kr«tdƒ‚t||d|… ƒt |||| … ¡tƒ d� ¡ }| |¡| ¡  }n|dkrÙtd|f ƒ‚|}t	 
d|dd	… ¡d
 }t	 
d|d	d… ¡d
 }||krÿtd||f ƒ‚|  |dd… ¡S )a*  
        Return a private key object corresponding to this OpenSSH private key
        string, in the "openssh-key-v1" format introduced in OpenSSH 6.5.

        The format of an openssh-key-v1 private key string is::
            -----BEGIN OPENSSH PRIVATE KEY-----
            <base64-encoded SSH protocol string>
            -----END OPENSSH PRIVATE KEY-----

        The SSH protocol string is as described in
        U{PROTOCOL.key<https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key>}.

        @type data: L{bytes}
        @param data: The key data.

        @type passphrase: L{bytes} or L{None}
        @param passphrase: The passphrase the key is encrypted with, or L{None}
        if it is not encrypted.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if
            * a passphrase is provided for an unencrypted key
            * the SSH protocol encoding is incorrect
        @raises EncryptedKeyError: if
            * a passphrase is not provided for an encrypted key
        ó    rd   éÿÿÿÿó   openssh-key-v1 z"unknown OpenSSH private key formatNé   ú!Lr\   r   zDonly OpenSSH private key files containing a single key are supportedrR   ó   noneú0Passphrase must be provided for an encrypted key)s
   aes128-ctrs
   aes192-ctró
   aes256-ctré   rx   é   úunknown encryption type ó   bcryptT)Úignore_few_roundszunknown KDF type zbad padding©Úbackendz*private key specifies KDF %r but no cipherz#check values do not match: %d != %d)ÚstripÚ
splitlinesr   Újoinr�   r(   Úlenr   rg   ÚstructÚunpackr1   r   ÚAESÚintÚbcryptÚkdfr   r   ÚCTRr	   Ú	decryptorÚupdateÚfinalizerŒ   )rK   rX   rD   ÚlinesÚkeyListÚcipherr¨   Ú
kdfOptionsrs   ru   Ú_ÚencPrivKeyListÚalgorithmClassÚ	blockSizeÚkeySizeÚivSizeÚsaltÚroundsÚdecKeyrª   ÚprivKeyListÚcheck1Úcheck2r.   r.   r/   Ú_fromPrivateOpenSSH_v1q  sl   
ÿÿú	ýüÿzKey._fromPrivateOpenSSH_v1c                    s@  |  ¡  ¡ }|d dd… }|d  d¡râ|stdƒ‚z|d  dd¡\}}| ¡  d	d¡\}‰ W n tyA   td
|d ›�ƒ‚w |dv r_tj	}t
| d¡d ƒd }	tˆ ƒdkr^tdƒ‚n|dkrstj}d}	tˆ ƒdkrrtdƒ‚ntd|›�ƒ‚tt‡ fdd„tdtˆ ƒdƒD ƒƒƒ}
t||
dd…  ƒ ¡ }t|| |
dd…  ƒ ¡ }|| d|	… }td |dd… ¡ƒ}t||ƒt |
¡tƒ d� ¡ }| |¡| ¡  }t|dd… ƒ}|d| … }nd |dd… ¡}t|ƒ}z	t |¡d }W n t�y } ztd|› �ƒ‚d}~ww |dk�r| t||tƒ ƒƒS |dk�r`t|ƒdk�r+|d }t|ƒdk �r6td ƒ‚d!d„ |dd"… D ƒ\}}}}}}}}| t j!||||||t j"||d#�d$� #tƒ ¡ƒS |d%k�r™d&d„ |dd… D ƒ\}}}}}t|ƒdk �r€td'ƒ‚| t$j%|t$j&|t$j'|||d(�d)�d*�j#tƒ d�ƒS td+|› �ƒ‚),aÉ  
        Return a private key object corresponding to this OpenSSH private key
        string, in the old PEM-based format.

        The format of a PEM-based OpenSSH private key string is::
            -----BEGIN <key type> PRIVATE KEY-----
            [Proc-Type: 4,ENCRYPTED
            DEK-Info: DES-EDE3-CBC,<initialization value>]
            <base64-encoded ASN.1 structure>
            ------END <key type> PRIVATE KEY------

        The ASN.1 structure of a RSA key is::
            (0, n, e, d, p, q)

        The ASN.1 structure of a DSA key is::
            (0, p, q, g, y, x)

        The ASN.1 structure of a ECDSA key is::
            (ECParameters, OID, NULL)

        @type data: L{bytes}
        @param data: The key data.

        @type passphrase: L{bytes} or L{None}
        @param passphrase: The passphrase the key is encrypted with, or L{None}
        if it is not encrypted.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if
            * a passphrase is provided for an unencrypted key
            * the ASN.1 encoding is incorrect
        @raises EncryptedKeyError: if
            * a passphrase is not provided for an encrypted key
        r   é   éïÿÿÿrd   ó   Proc-Type: 4,ENCRYPTEDr–   rR   ó    ó   ,zinvalid DEK-info )s   AES-128-CBCs   AES-256-CBCó   -r™   r‚   zAES encrypted key with a bad IVs   DES-EDE3-CBCé   r˜   zDES encrypted key with a bad IVrš   c                 3   s&   � | ]}t ˆ ||d  … dƒV  qdS )rR   r˜   N©r¦   ©r:   Úi©Úivdatar.   r/   r<     s   €$ z.Key._fromPrivateOpenSSH_PEM.<locals>.<genexpr>Nr�   r“   r‘   r�   z(Failed to decode key (Bad Passphrase?): s   ECs   RSArx   z!RSA key failed to decode properlyc                 s   ó   � | ]}t |ƒV  qd S ©NrÅ   ©r:   Úvaluer.   r.   r/   r<   -  ó   € é	   ©rt   ru   ©r^   r_   rz   Údmp1Údmq1ÚiqmpÚpublic_numberss   DSAc                 s   rÊ   rË   rÅ   rÌ   r.   r.   r/   r<   :  rÎ   z!DSA key failed to decode properlyr]   ra   ©r}   rÕ   úunknown key type )(rŸ   r    r�   r1   rŽ   ÚrstripÚ
ValueErrorr(   r   r¥   r¦   r¢   Ú	TripleDESÚbytesÚ	bytearrayÚranger   Údigestr   r¡   r   r   ÚCBCr	   rª   r«   r¬   ÚordÚ
berDecoderÚdecoder   r   r   ÚRSAPrivateNumbersri   Úprivate_keyr   ÚDSAPrivateNumbersrk   rl   )rK   rX   rD   r­   Úkindr±   ÚcipherIVInfor¯   r³   rµ   ÚivÚbaÚbbr¹   Úb64Datarª   ÚkeyDataÚ	removeLenÚ
decodedKeyÚ	asn1Errorru   rt   rz   r^   r_   rÒ   rÓ   rÔ   r`   rb   r}   r.   rÈ   r/   Ú_fromPrivateOpenSSH_PEMÊ  s¨   %ÿÿÿÿ ÿÿþ€ÿ

&ù÷
 ÿþûÿ	zKey._fromPrivateOpenSSH_PEMc                 C   s4   |  ¡  ¡ d dd… dkr|  ||¡S |  ||¡S )aø  
        Return a private key object corresponding to this OpenSSH private key
        string.  If the key is encrypted, passphrase MUST be provided.
        Providing a passphrase for an unencrypted key is an error.

        @type data: L{bytes}
        @param data: The key data.

        @type passphrase: L{bytes} or L{None}
        @param passphrase: The passphrase the key is encrypted with, or L{None}
        if it is not encrypted.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if
            * a passphrase is provided for an unencrypted key
            * the encoding is incorrect
        @raises EncryptedKeyError: if
            * a passphrase is not provided for an encrypted key
        r   r¾   r¿   s   OPENSSH)rŸ   r    r½   rð   )rK   rX   rD   r.   r.   r/   Ú_fromString_PRIVATE_OPENSSHH  s   zKey._fromString_PRIVATE_OPENSSHc                 C   sÊ   t  t|dd… ƒ¡}|d dksJ ‚i }|d dd… D ]\}}t t |¡¡d ||< q|d d dkrG| j|d |d |d	 |d
 d�S |d d dkrZ| j|d |d d�S td|d d › �ƒ‚)a  
        Return a public key corresponding to this LSH public key string.
        The LSH public key string format is::
            <s-expression: ('public-key', (<key type>, (<name, <value>)+))>

        The names for a RSA (key type 'rsa-pkcs1-sha1') key are: n, e.
        The names for a DSA (key type 'dsa') key are: y, g, p, q.

        @type data: L{bytes}
        @param data: The key data.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if the key type is unknown
        rd   r‘   r   ó
   public-keyNó   dsaó   yó   gó   pó   q©rb   r`   r^   r_   ó   rsa-pkcs1-sha1ó   nó   e©ru   rt   úunknown lsh key type )	r   Úparser   r   rh   ÚNSr…   r„   r(   ©rK   rX   ÚsexpÚkdr‡   r.   r.   r/   Ú_fromString_PUBLIC_LSHe  s   ÿzKey._fromString_PUBLIC_LSHc                 C   s0  t  |¡}|d dksJ ‚i }|d dd… D ]\}}t t |¡¡d ||< q|d d dkrPt|ƒdks<J t|ƒƒ‚| j|d |d |d	 |d
 |d d�S |d d dkr�t|ƒdksdJ t|ƒƒ‚|d	 |d
 kry|d
 |d	 |d	< |d
< | j|d |d |d |d	 |d
 d�S td|d d › �ƒ‚)a+  
        Return a private key corresponding to this LSH private key string.
        The LSH private key string format is::
            <s-expression: ('private-key', (<key type>, (<name>, <value>)+))>

        The names for a RSA (key type 'rsa-pkcs1-sha1') key are: n, e, d, p, q.
        The names for a DSA (key type 'dsa') key are: y, g, p, q, x.

        @type data: L{bytes}
        @param data: The key data.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if the key type is unknown
        r   ó   private-keyrd   Nró   r{   rô   rõ   rö   r÷   ó   xr|   ó	   rsa-pkcs1r™   rú   rû   ó   dry   rý   )	r   rþ   r   rh   rÿ   r¢   r…   r„   r(   r   r.   r.   r/   Ú_fromString_PRIVATE_LSH…  s$   
ÿÿzKey._fromString_PRIVATE_LSHc                 C   sð   t  |¡\}}|dkr8t  |¡\}}t  |¡\}}t  |¡\}}t  |¡\}}t  |¡\}}| j|||||d�S |dkrqt  |¡\}}t  |¡\}	}t  |¡\}
}t  |¡\}}t  |¡\}}t  |¡\}}| j|
||	|||d�S td|› �ƒ‚)aß  
        Return a private key object corresponsing to the Secure Shell Key
        Agent v3 format.

        The SSH Key Agent v3 format for a RSA key is::
            string 'ssh-rsa'
            integer e
            integer d
            integer n
            integer u
            integer p
            integer q

        The SSH Key Agent v3 format for a DSA key is::
            string 'ssh-dss'
            integer p
            integer q
            integer g
            integer y
            integer x

        @type data: L{bytes}
        @param data: The key data.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if the key type (the first string) is unknown
        r[   r|   rZ   ©ru   rt   rz   r^   r_   r‰   r×   )r   rg   rh   r…   r„   r(   )rK   rX   rr   r^   r_   r`   rb   r}   rt   rz   ru   r‰   r.   r.   r/   Ú_fromString_AGENTV3«  s"   zKey._fromString_AGENTV3c                 C   s¤   |  d¡s
|  d¡rdS |  d¡rdS |  d¡rdS |  d¡r!d	S |  d
¡s0|  d¡s0|  d¡rPt |¡\}}d}|rH|d7 }t |¡\}}|s;|dkrNdS dS dS )z¢
        Guess the type of key in data.  The types map to _fromString_*
        methods.

        @type data: L{bytes}
        @param data: The key data.
        s   ssh-ó   ecdsa-sha2-Úpublic_opensshs
   -----BEGINÚprivate_opensshó   {Ú
public_lshó   (Úprivate_lshs      ssh-s
      ecdsa-s      ssh-ed25519r   rd   r\   Úagentv3rq   N)r�   r   rg   rh   )rK   rX   Úignoredrs   Úcountr.   r.   r/   rS   Ü  s0   	


ÿþýþózKey._guessStringTypec           
   
   C   sn   t j||d�}|du r| tƒ ¡}| |ƒS t j|||t  ||¡t  ||¡t  ||¡|d�}	|	 tƒ ¡}| |ƒS )aÔ  
        Build a key from RSA numerical components.

        @type n: L{int}
        @param n: The 'n' RSA variable.

        @type e: L{int}
        @param e: The 'e' RSA variable.

        @type d: L{int} or L{None}
        @param d: The 'd' RSA variable (optional for a public key).

        @type p: L{int} or L{None}
        @param p: The 'p' RSA variable (optional for a public key).

        @type q: L{int} or L{None}
        @param q: The 'q' RSA variable (optional for a public key).

        @type u: L{int} or L{None}
        @param u: The 'u' RSA variable. Ignored, as its value is determined by
        p and q.

        @rtype: L{Key}
        @return: An RSA key constructed from the values as given.
        rÐ   NrÑ   )	r   ri   rj   r	   rã   Úrsa_crt_dmp1Úrsa_crt_dmq1Úrsa_crt_iqmprä   )
rK   ru   rt   rz   r^   r_   r‰   ÚpublicNumbersÚ	keyObjectÚprivateNumbersr.   r.   r/   r„   ü  s   õ


ù	zKey._fromRSAComponentsc           	      C   sX   t j|t j|||d�d�}|du r| tƒ ¡}| |ƒS t j||d�}| tƒ ¡}| |ƒS )a   
        Build a key from DSA numerical components.

        @type y: L{int}
        @param y: The 'y' DSA variable.

        @type p: L{int}
        @param p: The 'p' DSA variable.

        @type q: L{int}
        @param q: The 'q' DSA variable.

        @type g: L{int}
        @param g: The 'g' DSA variable.

        @type x: L{int} or L{None}
        @param x: The 'x' DSA variable (optional for a public key)

        @rtype: L{Key}
        @return: A DSA key constructed from the values as given.
        r]   ra   NrÖ   )r   rk   rl   rj   r	   rå   rä   )	rK   rb   r^   r_   r`   r}   r  r  r  r.   r.   r/   r…   )  s   ÿýzKey._fromDSAComponentsc                 C   sR   t j||t| d�}|du r| tƒ ¡}| |ƒS t j||d�}| tƒ ¡}| |ƒS )a«  
        Build a key from EC components.

        @param x: The affine x component of the public point used for verifying.
        @type x: L{int}

        @param y: The affine y component of the public point used for verifying.
        @type y: L{int}

        @param curve: NIST name of elliptic curve.
        @type curve: L{bytes}

        @param privateValue: The private value.
        @type privateValue: L{int}
        ©r}   rb   r€   N)Úprivate_valuerÕ   )r   ÚEllipticCurvePublicNumbersrm   rj   r	   ÚEllipticCurvePrivateNumbersrä   )rK   r}   rb   r€   r�   r  r  r  r.   r.   r/   Ú_fromECComponentsL  s   
ÿûÿzKey._fromECComponentsc                 C   s>   |du rt j t| |¡}| |ƒS t  |t| tƒ ¡}| |ƒS )aa  
        Build a key from an EC encoded point.

        @param encodedPoint: The public point encoded as in SEC 1 v2.0
        section 2.3.3.
        @type encodedPoint: L{bytes}

        @param curve: NIST name of elliptic curve.
        @type curve: L{bytes}

        @param privateValue: The private value.
        @type privateValue: L{int}
        N)r   rn   ro   rm   Úderive_private_keyr	   )rK   r   r€   r�   r  r.   r.   r/   rˆ   l  s   ÿüÿzKey._fromECEncodedPointc                 C   s0   |du rt j |¡}| |ƒS t j |¡}| |ƒS )a  Build a key from Ed25519 components.

        @param a: The Ed25519 public key, as defined in RFC 8032 section
            5.1.5.
        @type a: L{bytes}

        @param k: The Ed25519 private key, as defined in RFC 8032 section
            5.1.5.
        @type k: L{bytes}
        N)r   ÚEd25519PublicKeyÚfrom_public_bytesÚEd25519PrivateKeyÚfrom_private_bytes)rK   rv   rƒ   r  r.   r.   r/   rp   ˆ  s
   þzKey._fromEd25519Componentsc                 C   s
   || _ dS )zä
        Initialize with a private or public
        C{cryptography.hazmat.primitives.asymmetric} key.

        @param keyObject: Low level key.
        @type keyObject: C{cryptography.hazmat.primitives.asymmetric} key.
        N)Ú
_keyObject)Úselfr  r.   r.   r/   Ú__init__œ  s   
zKey.__init__ÚotherÚreturnc                 C   s.   t |tƒr|  ¡ | ¡ ko|  ¡ | ¡ kS tS )zN
        Return True if other represents an object with the same key.
        )r>   rF   rM   rX   ÚNotImplemented)r&  r(  r.   r.   r/   Ú__eq__¦  s   
 z
Key.__eq__c                 C   sš  |   ¡ dkrO|  ¡ }|d  d¡}|  ¡ r d|dd… › d�}n
d|dd… › d�}t| ¡ ƒD ]\}}|dkr@|d	|› �7 }q0|d
|› d|› �7 }q0|d S dt|   ¡ ƒ|  ¡ r[dp\d|  ¡ f g}t|  ¡  ¡ ƒD ]T\}}| d|› d�¡ |   ¡ dkr€|nt	 
|¡dd… }|r¿|dd… }|dd… }d}	t|ƒD ]}
|	t|
ƒd›d� }	q�t|ƒdk r¶|	dd… }	| d|	 ¡ |s‹qk|d d |d< d
 |¡S )z@
        Return a pretty representation of this object.
        ÚECr€   rP   z<Elliptic Curve Public Key (éýÿÿÿNz bits)z<Elliptic Curve Private Key (z	
curve:
	Ú
z:
	z>
z<%s %s (%s bits)z
Public KeyzPrivate Keyzattr ú:ÚEd25519r\   é   Ú Ú02xr‘   ú	ú>)rM   rX   râ   ÚisPublicÚsortedÚitemsr   ÚsizeÚappendr   ÚMPr   rà   r¢   r¡   )r&  rX   r‡   Úoutrƒ   Úvr­   ÚbyÚmÚor;   r.   r.   r/   Ú__repr__¯  sD   
ýÿÿ"ø€	
zKey.__repr__c                 C   s   t | jtjtjtjtj	fƒS )zl
        Check if this instance is a public key.

        @return: C{True} if this is a public key.
        )
r>   r%  r   ÚRSAPublicKeyr   ÚDSAPublicKeyr   rn   r   r!  ©r&  r.   r.   r/   r6  Û  s   üþzKey.isPublicc                 C   s   |   ¡ r| S t| j ¡ ƒS )zä
        Returns a version of this key containing only the public key data.
        If this is a public key, this may or may not be the same object
        as self.

        @rtype: L{Key}
        @return: A public key.
        )r6  rF   r%  rj   rD  r.   r.   r/   Úpublicë  s   	z
Key.publicc                 C   sb   |t ju rttt|  ¡ ƒ ¡ ƒƒS |t ju r*td dd„ t	t
|  ¡ ƒ ¡ ƒD ƒ¡ƒS td|› �ƒ‚)aO  
        The fingerprint of a public key consists of the output of the
        message-digest algorithm in the specified format.
        Supported formats include L{FingerprintFormats.MD5_HEX} and
        L{FingerprintFormats.SHA256_BASE64}

        The input to the algorithm is the public key data as specified by [RFC4253].

        The output of sha256[RFC4634] algorithm is presented to the
        user in the form of base64 encoded sha256 hashes.
        Example: C{US5jTUa0kgX5ZxdqaGF0yGRu8EgKXHNmoT8jHKo1StM=}

        The output of the MD5[RFC1321](default) algorithm is presented to the user as
        a sequence of 16 octets printed as hexadecimal with lowercase letters
        and separated by colons.
        Example: C{c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87}

        @param format: Format for fingerprint generation. Consists
            hash function and representation format.
            Default is L{FingerprintFormats.MD5_HEX}

        @since: 8.2

        @return: the user presentation of this L{Key}'s fingerprint, as a
        string.

        @rtype: L{str}
        ó   :c                 S   s   g | ]}t  |¡‘qS r.   )ÚbinasciiÚhexlify©r:   r}   r.   r.   r/   Ú
<listcomp>  s    z#Key.fingerprint.<locals>.<listcomp>z Unsupported fingerprint format: )r3   r5   r   r   r   rq   rÞ   r4   r¡   r   r   r2   )r&  Úformatr.   r.   r/   Úfingerprintù  s   

ÿÿzKey.fingerprintc                 C   sp   t | jtjtjfƒrdS t | jtjtjfƒrdS t | jtj	tj
fƒr$dS t | jtjtjfƒr0dS td| j›�ƒ‚)zÓ
        Return the type of the object we wrap.  Currently this can only be
        'RSA', 'DSA', 'EC', or 'Ed25519'.

        @rtype: L{str}
        @raises RuntimeError: If the object type is unknown.
        ÚRSAÚDSAr,  r0  zunknown type of object: )r>   r%  r   rB  ÚRSAPrivateKeyr   rC  ÚDSAPrivateKeyr   rn   ÚEllipticCurvePrivateKeyr   r!  r#  ÚRuntimeErrorrD  r.   r.   r/   rM   !  s   ÿÿzKey.typec                 C   s8   |   ¡ dkrdt| jjj d¡  S ddddœ|   ¡  S )aK  
        Get the type of the object we wrap as defined in the SSH protocol,
        defined in RFC 4253, Section 6.6. Currently this can only be b'ssh-rsa',
        b'ssh-dss' or b'ecdsa-sha2-[identifier]'.

        identifier is the standard NIST curve name

        @return: The key type format.
        @rtype: L{bytes}
        r,  r  r~   rZ   r[   re   )rM  rN  r0  )rM   r†   r%  r€   r‡   rB   rD  r.   r.   r/   ÚsshType8  s   ÿýüzKey.sshTypec                 C   s<   | j du rdS |  ¡ dkr| j jjS |  ¡ dkrdS | j jS )zv
        Return the size of the object we wrap.

        @return: The size of the key.
        @rtype: L{int}
        Nr   r,  r0  é   )r%  rM   r€   Úkey_sizerD  r.   r.   r/   r9  N  s   

zKey.sizec              	   C   s¼  t | jtjƒr| j ¡ }|j|jdœS t | jtjƒr5| j ¡ }|jj|jj|j	|j
|jt |j|j
¡dœS t | jtjƒrO| j ¡ }|j|jj|jj
|jjdœS t | jtjƒro| j ¡ }|j|jj|jjj|jjj
|jjjdœS t | jtjƒr…| j ¡ }|j|j|  ¡ dœS t | jtjƒrŸ| j ¡ }|jj|jj|j|  ¡ dœS t | jtjƒr³d| j tjjtjj¡iS t | jtj ƒrÖ| j !¡  tjjtjj¡| j "tjjtj#jt $¡ ¡dœS t%d	| j› �ƒ‚)
z_
        Return the values of the public key as a dictionary.

        @rtype: L{dict}
        rü   r	  rø   )r}   rb   r`   r^   r_   r  )r}   rb   r�   r€   rv   )rv   rƒ   zUnexpected key type: )&r>   r%  r   rB  rÕ   ru   rt   rO  Úprivate_numbersrz   r^   r_   r  r   rC  rb   rc   r`   rP  r}   r   rn   rS  rQ  r  r   r!  Úpublic_bytesr   ÚEncodingÚRawÚPublicFormatr#  rj   Úprivate_bytesÚPrivateFormatÚNoEncryptionrR  )r&  Únumbersr.   r.   r/   rX   ]  st   
þ
ù	
ü
û
ý
üÿÿ
ÿýüzKey.datac                 C   s  |   ¡ }|  ¡ }|dkrt d¡t |d ¡ t |d ¡ S |dkrDt d¡t |d ¡ t |d ¡ t |d	 ¡ t |d
 ¡ S |dkrx| jjjd d }t |d ¡t |d dd… ¡ t dt 	|d |¡ t 	|d
 |¡ ¡ S |dkrˆt d¡t |d ¡ S t
d|› �ƒ‚)a•  
        Return the public key blob for this key. The blob is the
        over-the-wire format for public keys.

        SECSH-TRANS RFC 4253 Section 6.6.

        RSA keys::
            string 'ssh-rsa'
            integer e
            integer n

        DSA keys::
            string 'ssh-dss'
            integer p
            integer q
            integer g
            integer y

        EC keys::
            string 'ecdsa-sha2-[identifier]'
            integer x
            integer y

            identifier is the standard NIST curve name

        Ed25519 keys::
            string 'ssh-ed25519'
            string a

        @rtype: L{bytes}
        rM  rZ   rt   ru   rN  r[   r^   r_   r`   rb   r,  é   r™   r€   éøÿÿÿNó   r}   r0  re   rv   úunknown key type: )rM   rX   r   rÿ   r;  r%  r€   rU  r   r   r(   )r&  rM   rX   Ú
byteLengthr.   r.   r/   rq   ©  s@    &ÿþýüÿÿÿþÿþÿ	zKey.blobc                 C   s€  |   ¡ }|  ¡ }|dkrCt |d |d ¡}t d¡t |d ¡ t |d ¡ t |d ¡ t |¡ t |d ¡ t |d ¡ S |dkrot d	¡t |d ¡ t |d ¡ t |d
 ¡ t |d ¡ t |d ¡ S |dkrž| j ¡  	t
jjt
jj¡}t |d ¡t |d dd… ¡ t |¡ t |d ¡ S |dkr¹t d¡t |d ¡ t |d |d  ¡ S td|› �ƒ‚)a1  
        Return the private key blob for this key. The blob is the
        over-the-wire format for private keys:

        Specification in OpenSSH PROTOCOL.agent

        RSA keys::

            string 'ssh-rsa'
            integer n
            integer e
            integer d
            integer u
            integer p
            integer q

        DSA keys::

            string 'ssh-dss'
            integer p
            integer q
            integer g
            integer y
            integer x

        EC keys::

            string 'ecdsa-sha2-[identifier]'
            integer x
            integer y
            integer privateValue

            identifier is the NIST standard curve name.

        Ed25519 keys::

            string 'ssh-ed25519'
            string a
            string k || a
        rM  r^   r_   rZ   ru   rt   rz   rN  r[   r`   rb   r}   r,  r€   r`  Nr�   r0  re   rv   rƒ   rb  )rM   rX   r   r  r   rÿ   r;  r%  rj   rW  r   rX  ÚX962rZ  ÚUncompressedPointr(   )r&  rM   rX   rÔ   ÚencPubr.   r.   r/   ÚprivateBlobå  sh   )ÿþýüûúÿ	ÿþýüûÿ
þÿþýÿÿþÿzKey.privateBlobÚextraÚcommentrD   c                 C   s€   |durt jdtdd� |  ¡ r|}n|}t|tƒr| d¡}t|ƒ}t| d| 	¡ › �dƒ}|du r9t
d|› �ƒ‚||||d�S )	a  
        Create a string representation of this key.  If the key is a private
        key and you want the representation of its public key, use
        C{key.public().toString()}.  type maps to a _toString_* method.

        @param type: The type of string to emit.  Currently supported values
            are C{'OPENSSH'}, C{'LSH'}, and C{'AGENTV3'}.
        @type type: L{str}

        @param extra: Any extra data supported by the selected format which
            is not part of the key itself.  For public OpenSSH keys, this is
            a comment.  For private OpenSSH keys, this is a passphrase to
            encrypt with.  (Deprecated since Twisted 20.3.0; use C{comment}
            or C{passphrase} as appropriate instead.)
        @type extra: L{bytes} or L{unicode} or L{None}

        @param subtype: A subtype of the requested C{type} to emit.  Only
            supported for private OpenSSH keys, for which the currently
            supported subtypes are C{'PEM'} and C{'v1'}.  If not given, an
            appropriate default is used.
        @type subtype: L{str} or L{None}

        @param comment: A comment to include with the key.  Only supported
            for OpenSSH keys.

            Present since Twisted 20.3.0.

        @type comment: L{bytes} or L{unicode} or L{None}

        @param passphrase: A passphrase to encrypt the key with.  Only
            supported for private OpenSSH keys.

            Present since Twisted 20.3.0.

        @type passphrase: L{bytes} or L{unicode} or L{None}

        @rtype: L{bytes}
        Nz„The 'extra' argument to twisted.conch.ssh.keys.Key.toString was deprecated in Twisted 20.3.0; use 'comment' or 'passphrase' instead.r“   )Ú
stacklevelrP   Ú
_toString_rb  )Úsubtyperi  rD   )ÚwarningsÚwarnÚDeprecationWarningr6  r>   r?   rB   rE   rT   rU   r(   )r&  rM   rh  rl  ri  rD   rY   r.   r.   r/   ÚtoString8  s    -û

zKey.toStringc                 C   sn   |   ¡ dkr|s
d}| j tjjtjj¡d |  ¡ S t|  	¡ ƒ 
dd¡}|s)d}|  ¡ d | d |  ¡ S )a  
        Return a public OpenSSH key string.

        See _fromString_PUBLIC_OPENSSH for the string format.

        @type comment: L{bytes} or L{None}
        @param comment: A comment to include with the key, or L{None} to
        omit the comment.
        r,  r�   rÁ   ó   
)rM   r%  rW  r   rX  ÚOpenSSHrZ  rŸ   r   rq   ÚreplacerS  )r&  ri  rë   r.   r.   r/   Ú_toPublicOpenSSHz  s    
ÿýüúzKey._toPublicOpenSSHc                    s¨  |r%t j}d}d}|jd }d}|}t |¡}	d}
t |	¡t d|
¡ }nd}d}d}d}t d	¡}|| |  	¡  t |p>d¡ }d
}t
|ƒ| r\|d7 }|t|d@ fƒ7 }t
|ƒ| sI|r‹t ||	|| d¡}t||d|… ƒt |||| … ¡tƒ d� ¡ }| |¡| ¡  }n|}dt |¡ t |¡ t |¡ t dd¡ t |  ¡ ¡ t |¡ }t|ƒ dd¡‰ dg‡ fdd„td
t
ˆ ƒdƒD ƒ dg }d |¡d S )aP  
        Return a private OpenSSH key string, in the "openssh-key-v1" format
        introduced in OpenSSH 6.5.

        See _fromPrivateOpenSSH_v1 for the string format.

        @type passphrase: L{bytes} or L{None}
        @param passphrase: The passphrase to encrypt the key with, or L{None}
        if it is not encrypted.
        r—   r›   r™   r‚   éd   r”   r•   r�   r\   r   rd   éÿ   Nr�   r’   rq  s#   -----BEGIN OPENSSH PRIVATE KEY-----c                    ó   g | ]
}ˆ ||d  … ‘qS ©é@   r.   rÆ   ©rë   r.   r/   rJ  Í  ó    z,Key._toPrivateOpenSSH_v1.<locals>.<listcomp>ry  s!   -----END OPENSSH PRIVATE KEY-----)r   r¥   Ú
block_sizer   ÚsecureRandomr   rÿ   r£   Úpackrg  r¢   rÛ   r§   r¨   r   r   r©   r	   Ú	encryptorr«   r¬   rq   r   rs  rÝ   r¡   )r&  ri  rD   r¯   Ú
cipherNameÚkdfNamer´   rµ   r¶   r·   r¸   r°   Úcheckrº   ÚpadByteÚencKeyr  r²   rq   r­   r.   rz  r/   Ú_toPrivateOpenSSH_v1”  sl   


þýüÿþý
üûúÿ	ÿþÿzKey._toPrivateOpenSSH_v1c              
      sl  |   ¡ dkr|st ¡ }nt |¡}| j tjjtjj	|¡S |   ¡ dkr(t
dƒ‚|  ¡ }d d|   ¡  d¡df¡g}|   ¡ dkrm|d	 |d
 }}t ||¡}d|d |d |d |||d |d  |d |d  |f	}nd|d	 |d
 |d |d |d f}t ¡ }	tt ¡ |ƒD ]\}
}|	 |
t |¡¡ qŠt |	¡}|�rt d¡}d dd„ t|ƒD ƒ¡}| d¡}| d¡ | d| d ¡ t|| ƒ ¡ }t|| | ƒ ¡ }|| dd… }dt|ƒd  }|t|fƒ| 7 }t t! "|¡t# $|¡t%ƒ d� &¡ }| '|¡| (¡  }t)|ƒ *dd¡‰ |‡ fdd„t+dtˆ ƒdƒD ƒ7 }| d d|   ¡  d¡df¡¡ d |¡S ) a,  
        Return a private OpenSSH key string, in the old PEM-based format.

        See _fromPrivateOpenSSH_PEM for the string format.

        @type passphrase: L{bytes} or L{None}
        @param passphrase: The passphrase to encrypt the key with, or L{None}
        if it is not encrypted.
        r,  r0  zBcannot serialize Ed25519 key to OpenSSH PEM format; use v1 insteadr�   s   -----BEGIN r~   s    PRIVATE KEY-----rM  r^   r_   r   ru   rt   rz   rd   r`   rb   r}   r™   r2  c                 S   s   g | ]}t |ƒd ›‘qS )Ú02X)rà   rI  r.   r.   r/   rJ  
  s    z-Key._toPrivateOpenSSH_PEM.<locals>.<listcomp>rÀ   s   DEK-Info: DES-EDE3-CBC,rq  NrÄ   r�   c                    rw  rx  r.   rÆ   rz  r.   r/   rJ    r{  ry  s	   -----END ),rM   r   r]  ÚBestAvailableEncryptionr%  r[  rX  ÚPEMr\  ÚTraditionalOpenSSLrÙ   rX   r¡   rB   r   r  r   ÚSequenceÚzipÚ	itertoolsr  ÚsetComponentByPositionÚIntegerÚ
berEncoderr   r}  r   r:  r   rÞ   r¢   rÛ   r   r   rÚ   r   rß   r	   r  r«   r¬   r   rs  rÝ   )r&  rD   r  rX   r­   r^   r_   rÔ   ÚobjDataÚasn1SequenceÚindexrÍ   Úasn1Datarè   Úhexivré   rê   r„  ÚpadLenr.   rz  r/   Ú_toPrivateOpenSSH_PEMÒ  sv   


ýÿÿÿ÷$



ÿþ"ÿ
zKey._toPrivateOpenSSH_PEMc                 C   sh   |   ¡ r
| j|d�S |dks|du r|  ¡ dkr| j||d�S |du s'|dkr-| j|d�S td|› �ƒ‚)	ar  
        Return a public or private OpenSSH string.  See
        L{_fromString_PUBLIC_OPENSSH} and L{_fromPrivateOpenSSH_PEM} for the
        string formats.

        @param subtype: A subtype to emit.  Only supported for private keys,
            for which the currently supported subtypes are C{'PEM'} and C{'v1'}.
            If not given, an appropriate default is used.
        @type subtype: L{str} or L{None}

        @param comment: Comment for a public key.
        @type comment: L{bytes}

        @param passphrase: Passphrase for a private key.
        @type passphrase: L{bytes}

        @rtype: L{bytes}
        )ri  Úv1Nr0  )ri  rD   rˆ  rC   zunknown subtype )r6  rt  rM   r…  r–  rÙ   )r&  rl  ri  rD   r.   r.   r/   Ú_toString_OPENSSH!  s   zKey._toString_OPENSSHc                 K   s¨  |   ¡ }|  ¡ }|  ¡ rƒ|dkr2t dddt |d ¡dd… gdt |d	 ¡dd… gggg¡}nE|d
krpt dddt |d ¡dd… gdt |d ¡dd… gdt |d ¡dd… gdt |d ¡dd… gggg¡}ntd|› �ƒ‚dt|ƒ 	dd¡ d S |dk�r|d |d }}t
 ||¡}t dddt |d ¡dd… gdt |d	 ¡dd… gdt |d ¡dd… gdt |¡dd… gdt |¡dd… gdt |d |d  ¡dd… gdt |d |d  ¡dd… gd t |¡dd… gg	gg¡S |d
k�rLt dddt |d ¡dd… gdt |d ¡dd… gdt |d ¡dd… gdt |d ¡dd… gd!t |d" ¡dd… gggg¡S td|› d#�ƒ‚)$z¤
        Return a public or private LSH key.  See _fromString_PUBLIC_LSH and
        _fromString_PRIVATE_LSH for the key formats.

        @rtype: L{bytes}
        rM  rò   rù   rú   ru   r\   Nrû   rt   rN  ró   rö   r^   r÷   r_   rõ   r`   rô   rb   r×   r  rq  r�   ó   }r  r  r  rz   ó   ard   ó   bó   cr  r}   ú')rX   rM   r6  r   r~  r   r;  r(   r   rs  r   r  )r&  ÚkwargsrX   rM   rì   r^   r_   rÔ   r.   r.   r/   Ú_toString_LSH>  sv   ýþÿÿûþÿÿ
  ÷þÿÿ
úþÿÿzKey._toString_LSHc                 K   s˜   |   ¡ }|  ¡ sJ|  ¡ dkr#|d |d |d |d |d |d f}n|  ¡ dkr:|d |d |d	 |d
 |d f}t |  ¡ ¡d ttj|ƒ¡ S dS )zŒ
        Return a private Secure Shell Agent v3 key.  See
        _fromString_AGENTV3 for the key format.

        @rtype: L{bytes}
        rM  rt   rz   ru   r‰   r^   r_   rN  r`   rb   r}   r�   N)	rX   r6  rM   r   rÿ   rS  r¡   Úmapr;  )r&  rž  rX   Úvaluesr.   r.   r/   Ú_toString_AGENTV3�  s   ú" ôzKey._toString_AGENTV3c                 C   s–  |   ¡ }|dkr| j |t ¡ t ¡ ¡}t |¡}n¨|dkr;| j |t ¡ ¡}t	|ƒ\}}t t
|dƒt
|dƒ ¡}n‡|dkrµ|  ¡ }|dkrLt ¡ }n|dkrUt ¡ }nt ¡ }| j |t |¡¡}	t	|	ƒ\}}t
|ƒ}
t
|ƒ}t |
d ƒtu r€t|
d ƒ}n|
d }|d@ rŒd	|
 }
t |d ƒtu r›t|d ƒ}n|d }|d@ r§d	| }t t |
¡t |¡ ¡}n|d
krÂt | j |¡¡}t |  ¡ ¡| S )zê
        Sign some data with this key.

        SECSH-TRANS RFC 4253 Section 6.6.

        @type data: L{bytes}
        @param data: The data to sign.

        @rtype: L{bytes}
        @return: A signature for the given data.
        rM  rN  é   r,  rT  é€  r   é€   ó    r0  )rM   r%  Úsignr   ÚPKCS1v15r
   ÚSHA1r   rÿ   r#   r   r9  ÚSHA256ÚSHA384ÚSHA512r   ÚECDSAr?   rà   rS  )r&  rX   rr   ÚsigÚretÚrÚsrµ   ÚhashSizeÚ	signaturerG   ÚsbÚrcompÚscompr.   r.   r/   r§  ¦  sB   

zKey.signc                 C   sì  t |ƒdkrdt |¡}}nt |¡\}}||  ¡ krdS |  ¡ }|dkrA| j}|  ¡ s1| ¡ }t |¡d |t	 
¡ t ¡ f}n¢|dkrxt |¡d }t |dd… d	¡}t |dd… d	¡}	t||	ƒ}| j}|  ¡ sp| ¡ }||t ¡ f}nk|d
krËt |¡d }t |d¡\}
}}t |
d	¡}t |d	¡}	t||	ƒ}| j}|  ¡ s¨| ¡ }|  ¡ }|dkrµt ¡ }n|dkr¾t ¡ }nt ¡ }||t |¡f}n|dkrã| j}|  ¡ sÚ| ¡ }t |¡d |f}z|j|Ž  W dS  tyõ   Y dS w )a  
        Verify a signature using this key.

        @type signature: L{bytes}
        @param signature: The signature to verify.

        @type data: L{bytes}
        @param data: The signed data.

        @rtype: L{bool}
        @return: C{True} if the signature is valid.
        é(   r[   FrM  r   rN  Nr£  Úbigr,  rR   rT  r¤  r0  T)r¢   r   rÿ   rg   rS  rM   r%  r6  rj   r   r¨  r
   r©  r¦   Ú
from_bytesr$   r9  rª  r«  r¬  r   r­  Úverifyr   )r&  r³  rX   ÚsignatureTyperr   rƒ   ÚargsÚconcatenatedSignaturer°  r±  ÚrstrÚsstrrs   rµ   r²  r.   r.   r/   rº  è  sf   ü



ýÿz
Key.verify)NN)NNNNrË   )NNN)1r*   r+   r,   r-   ÚclassmethodrO   rI   rw   rŒ   r�   r½   rð   rñ   r  r  r
  rS   r„   r…   r  rˆ   rp   r'  ÚobjectÚboolr+  r?   rA  r6  rE  r3   r4   rL  rM   rS  r9  rX   rq   rg  r"   rp  rt  r…  r–  r˜  rŸ  r¢  r§  rº  r.   r.   r.   r/   rF   ’   s|    '
8
J

X
}


%
0
,"
	,(L<Sþÿ
<

>
ORBrF   é   c                 C   sœ   |   ¡ jdd� |  ¡ s(tjd|tƒ d�}|jtjj	tj
jt ¡ d�}|  |¡ |  d¡�}tj| ¡ dtƒ d�}t|ƒW  d  ƒ S 1 sGw   Y  dS )	a¿  
    This function returns a persistent L{Key}.

    The key is loaded from a PEM file in C{location}. If it does not exist, a
    key with the key size of C{keySize} is generated and saved.

    @param location: Where the key is stored.
    @type location: L{twisted.python.filepath.FilePath}

    @param keySize: The size of the key, if it needs to be generated.
    @type keySize: L{int}

    @returns: A persistent key.
    @rtype: L{Key}
    T)ÚignoreExistingDirectoryi  )Úpublic_exponentrU  rž   )ÚencodingrK  Úencryption_algorithmrG   N)Úpasswordrž   )ÚparentÚmakedirsÚexistsr   Úgenerate_private_keyr	   r[  r   rX  rˆ  r\  r‰  r]  Ú
setContentrH   r   rJ   rF   )Úlocationrµ   Ú
privateKeyÚpemÚkeyFiler.   r.   r/   Ú_getPersistentRSAKey5  s"   ÿý
ÿ$ürÒ  )rÃ  )Pr-   rG  rŒ  r£   r8   rm  Úbase64r   r   r   Úhashlibr   r   r§   Úcryptographyr   Úcryptography.exceptionsr   Úcryptography.hazmat.backendsr	   Úcryptography.hazmat.primitivesr
   r   Ú)cryptography.hazmat.primitives.asymmetricr   r   r   r   r   Ú&cryptography.hazmat.primitives.ciphersr   r   r   Ú,cryptography.hazmat.primitives.serializationr   r   Úpyasn1.codec.berr   rá   r   r�  Úpyasn1.errorr   Úpyasn1.typer   Útwisted.conch.sshr   r   Útwisted.conch.ssh.commonr   Útwisted.pythonr   Útwisted.python.compatr   r   Útwisted.python.constantsr    r!   Útwisted.python.deprecater"   Ú/cryptography.hazmat.primitives.asymmetric.utilsr#   r$   ÚImportErrorr%   r&   Ú	SECP256R1Ú	SECP384R1Ú	SECP521R1rm   r†   Ú	Exceptionr(   r1   r2   r3   r6   rE   rF   rÒ  r.   r.   r.   r/   Ú<module>   sv   ÿ	ýý             0