U
    `[
                     @   s  d Z ddlmZmZ ddlZddl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mZ ddlmZmZmZmZ dd	lmZmZ dd
lmZ zddlmZmZ W n$ ek
r   ddlmZm Z Y nX ddl!m"Z"m#Z#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z+ ddl)m,Z- ddl.m/Z/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z>m?Z@ ddlAmBZBmCZC eD eE eF dZGddddZHG dd deIZJG dd deIZKG d d! d!eIZLG d"d# d#eCZMG d$d% d%eNZOd)d'd(ZPdS )*z$
Handling of RSA, DSA, and EC keys.
    )absolute_importdivisionN)md5sha256)InvalidSignature)default_backend)hashesserialization)dsarsapaddingec)load_pem_private_keyload_ssh_public_key)utils)encode_dss_signaturedecode_dss_signature)encode_rfc6979_signaturedecode_rfc6979_signature)Cipher
algorithmsmodes)PyAsn1Error)univ)decoder)encoder)commonsexpy)int_from_bytesint_to_bytes)	randbytes)	iterbyteslongizipnativeStringunicode_PY3_b64decodebytes_b64encodebytes)NamedConstantNames)s   ecdsa-sha2-nistp256s   ecdsa-sha2-nistp384s   ecdsa-sha2-nistp521s   nistp256s   nistp384s   nistp521)s	   secp256r1s	   secp384r1s	   secp521r1c                   @   s   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__ r1   r1   8/usr/lib/python3/dist-packages/twisted/conch/ssh/keys.pyr+   A   s   r+   c                   @   s   e Zd ZdZdS )EncryptedKeyErrorzb
    Raised when an encrypted key is presented to fromString/fromFile without
    a password.
    Nr,   r1   r1   r1   r2   r3   J   s   r3   c                   @   s   e Zd ZdZdS )BadFingerPrintFormatzS
    Raises when unsupported fingerprint formats are presented to fingerprint.
    Nr,   r1   r1   r1   r2   r4   R   s   r4   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/   r0   r)   MD5_HEXSHA256_BASE64r1   r1   r1   r2   r5   Y   s   r5   c                   @   sV  e Zd ZdZedCddZedDd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dEddZedFddZedGddZdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zejfd)d*Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 Z dHd7d8Z!d9d: Z"d;d< Z#d=d> Z$d?d@ Z%dAdB Z&dS )I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   s4   t |d }| | ||W  5 Q R  S Q R X 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type
passphrasefr1   r1   r2   fromFiles   s    zKey.fromFilec                 C   s   t |tr|d}t |tr(|d}|dkr:| |}|dkrPtd|f t| d| f d}|dkr|td|f |jjdkr|rtd||S |||S d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 %rz_fromString_%szno _fromString method for %s   zkey not encrypted)	
isinstancer%   encode_guessStringTyper+   getattrupper__code__co_argcount)r=   datar?   r@   methodr1   r1   r2   r;      s     




zKey.fromStringc           
      C   s   t |\}}|dkr@t |d\}}}| t||t S |dkrt |d\}}}}	}| tj|	tj	|||ddt S |t
kr| tjt
| t |dd t S td|f d	S )
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.

        @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-rsarD      ssh-dss   pqgyparameter_numbers   unknown blob type: %sN)r   getNSgetMPr   RSAPublicNumbers
public_keyr   r
   DSAPublicNumbersDSAParameterNumbers_curveTabler   EllipticCurvePublicNumbersZfrom_encoded_pointr+   )
r=   blobkeyTyperestenrR   rS   rT   rV   r1   r1   r2   _fromString_BLOB   s<    
zKey._fromString_BLOBc                 C   s   t |\}}|dkrDt |d\}}}}}}	}| j|||||	dS |dkrxt |d\}}	}
}}}| j||
||	|dS |dd tt D krt |d	\}}}}| j||||d
S t	d|f dS )aq  
        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]'
            integer x
            integer y
            integer privateValue

            identifier is the standard NIST curve name.


        @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.
        rN      rf   re   drR   rS   rO      rV   rT   rR   rS   xc                 S   s   g | ]}|qS r1   r1   ).0curver1   r1   r2   
<listcomp>  s     z0Key._fromString_PRIVATE_BLOB.<locals>.<listcomp>   )rm   rV   ro   privateValuerY   N)
r   rZ   r[   _fromRSAComponents_fromDSAComponentslistr`   keys_fromECComponentsr+   )r=   rb   rc   rd   rf   re   rj   urR   rS   rT   rV   rm   rr   r1   r1   r2   _fromString_PRIVATE_BLOB   s    '
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-sha2rX   )
startswithr   r   decodebytessplitrg   )r=   rL   rb   r1   r1   r2   _fromString_PUBLIC_OPENSSH%  s    
zKey._fromString_PUBLIC_OPENSSHc                    sZ  |   }|d dd }|d dr|s8tdz,|d dd\}}| d	d\} W n& tk
r   td
|d f Y nX |dkrtj	}t
t
|dd d }	t dkrtdn6|dkrtj}d}	t dkrtdntd|f 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 n2 tk
r. } ztd|f W 5 d}~X Y nX |dkrL| t||t S |dkrt|dkrl|d }t|dk rtd d!d |dd" D \}}}}}}}}| t j!||||||t j"||d#d$#t S |d%krHd&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+|f d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.

        The format of an 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      irX      Proc-Type: 4,ENCRYPTEDz0Passphrase must be provided for an encrypted keyrD          ,zinvalid DEK-info %r)s   AES-128-CBCs   AES-256-CBC   -       zAES encrypted key with a bad IVs   DES-EDE3-CBC      zDES encrypted key with a bad IVzunknown encryption type %rc                    s"   g | ]}t  ||d   dqS )rD   r   )intrn   iZivdatar1   r2   rp   |  s   z3Key._fromString_PRIVATE_OPENSSH.<locals>.<listcomp>N    rq   backendz*Failed to decode key (Bad Passphrase?): %ss   ECs   RSArh   z!RSA key failed to decode properlyc                 S   s   g | ]}t |qS r1   r"   rn   valuer1   r1   r2   rp     s    	   re   rf   rR   rS   rj   dmp1dmq1iqmppublic_numberss   DSAc                 S   s   g | ]}t |qS r1   r   r   r1   r1   r2   rp     s     z!DSA key failed to decode properlyrQ   rU   rm   r   unknown key type %s)(strip
splitlinesrz   r3   r|   rstrip
ValueErrorr+   r   ZAESr   len	TripleDESbytes	bytearrayranger   digestr{   joinr   r   CBCr   	decryptorupdatefinalizeord
berDecoderdecoder   r   r   RSAPrivateNumbersr\   private_keyr
   DSAPrivateNumbersr^   r_   )r=   rL   r@   linesZkind_ZcipherIVInfoZcipherZalgorithmClasskeySizeivbabbZdecKeyb64Datar   keyDataZ	removeLenZ
decodedKeyre   rf   rj   rR   rS   r   r   r   rT   rV   rm   r1   r   r2   _fromString_PRIVATE_OPENSSH:  s    &







 
zKey._fromString_PRIVATE_OPENSSHc                 C   s   t t|dd }|d dks&ti }|d dd D ] \}}tt|d ||< q:|d d dkr| j|d |d |d	 |d
 dS |d d dkr| j|d |d dS t	d|d d f dS )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
        rX   r   r   
   public-keyN   dsa   y   g   p   qrV   rT   rR   rS      rsa-pkcs1-sha1   n   erf   re   unknown lsh key type %s)
r   parser{   AssertionErrorr   r[   NSrt   rs   r+   r=   rL   ZsexpZkdnamer1   r1   r2   _fromString_PUBLIC_LSH  s       zKey._fromString_PUBLIC_LSHc                 C   s6  t |}|d dksti }|d dd D ] \}}tt|d ||< q.|d d dkrt|dksxtt|| j|d |d |d	 |d
 |d dS |d d dkrt|dkstt||d	 |d
 kr|d
 |d	  |d	< |d
< | j|d |d |d |d	 |d
 dS t	d|d d f dS )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-keyrX   Nr   rk   r   r   r   r      xrl   	   rsa-pkcs1r   r   r      dri   r   )
r   r   r   r   r[   r   r   rt   rs   r+   r   r1   r1   r2   _fromString_PRIVATE_LSH  s4    
        zKey._fromString_PRIVATE_LSHc                 C   s   t |\}}|dkrpt |\}}t |\}}t |\}}t |\}}t |\}}| j|||||dS |dkrt |\}}t |\}	}t |\}
}t |\}}t |\}}t |\}}| j|
||	|||dS td|f dS )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
        rO   rl   rN   rf   re   rj   rR   rS   rx   r   N)r   rZ   r[   rt   rs   r+   )r=   rL   rc   rR   rS   rT   rV   rm   re   rj   rf   rx   r1   r1   r2   _fromString_AGENTV3  s"    zKey._fromString_AGENTV3c                 C   s   | ds| drdS | dr&dS | dr4dS | drBd	S | d
sV| drt|\}}d}|r|d7 }t|\}}qh|dkrd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-Zpublic_opensshs
   -----BEGINZprivate_openssh   {Z
public_lsh   (Zprivate_lshs      ssh-s
      ecdsa-r   rX   rP   Zagentv3rb   N)rz   r   rZ   r[   )r=   rL   Zignoredrd   countr1   r1   r2   rG   6  s"    	


zKey._guessStringTypec           
   
   C   sh   t j||d}|dkr$|t }n<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   r\   r]   r   r   Zrsa_crt_dmp1Zrsa_crt_dmq1rsa_crt_iqmpr   )
r=   rf   re   rj   rR   rS   rx   publicNumbers	keyObjectprivateNumbersr1   r1   r2   rs   R  s    


	zKey._fromRSAComponentsc           	      C   sR   t j|t j|||dd}|dkr0|t }n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.
        rQ   rU   Nr   )r
   r^   r_   r]   r   r   r   )	r=   rV   rR   rS   rT   rm   r   r   r   r1   r1   r2   rt     s      zKey._fromDSAComponentsc                 C   sL   t j||t| d}|dkr*|t }n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}
        rm   rV   ro   N)private_valuer   )r   ra   r`   r]   r   ZEllipticCurvePrivateNumbersr   )r=   rm   rV   ro   rr   r   r   r   r1   r1   r2   rw     s       zKey._fromECComponentsc                 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   r1   r1   r2   __init__  s    zKey.__init__c                 C   s8   t | t |kr0|   |  ko.|  | kS tS dS )zN
        Return True if other represents an object with the same key.
        N)r?   rL   NotImplemented)r   otherr1   r1   r2   __eq__  s     z
Key.__eq__c                 C   s   |  |}|tkr|S | S )zO
        Return True if other represents anything other than this key.
        )r   r   )r   r   resultr1   r1   r2   __ne__  s    
z
Key.__ne__c                 C   s  |   dkr|  }|d d}|  r>d|dd f }nd|dd f }t| D ]4\}}tr|dkr|d|f 7 }q\|d	||f 7 }q\|d
 S dt|   |  rdpd| jj	f g}t|   D ]\}}|
d|f  t|dd }|r|dd }|dd }d}	t|D ]}
|	dt|
f  }	q$t|dk rX|	dd }	|
d|	  qq|d d |d< d|S dS )z@
        Return a pretty representation of this object.
        ECro   rC   z$<Elliptic Curve Public Key (%s bits)Nz%<Elliptic Curve Private Key (%s bits)z
curve:
	%sz
%s:
	%sz>
z<%s %s (%s bits)z
Public KeyzPrivate Keyzattr %s:rP       z%02x:r   	>
)r?   rL   r   isPublicsorteditemsr&   r$   r   key_sizeappendr   MPr!   r   r   r   )r   rL   r   outkvr   Zbymocr1   r1   r2   __repr__  s>    
zKey.__repr__c                 C   s   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.
        )rE   r   r   RSAPublicKeyr
   DSAPublicKeyr   EllipticCurvePublicKeyr   r1   r1   r2   r     s    zKey.isPublicc                 C   s   |   r| S t| j S d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.
        N)r   r8   r   r]   r   r1   r1   r2   public  s    	z
Key.publicc                 C   sh   |t jkr$ttt|   S |t jkrVtd	dd t
t|   D S td|f dS )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 r1   )binasciiZhexlifyrn   rm   r1   r1   r2   rp   ?  s   z#Key.fingerprint.<locals>.<listcomp>z"Unsupported fingerprint format: %sN)r5   r7   r$   base64Z	b64encoder   rb   r   r6   r   r!   r   r4   )r   formatr1   r1   r2   fingerprint  s    


zKey.fingerprintc                 C   s\   t | jtjtjfrdS t | jtjtjfr0dS t | jtj	tj
frHdS td| jf dS )z
        Return the type of the object we wrap.  Currently this can only be
        'RSA', 'DSA', or 'EC'.

        @rtype: L{str}
        @raises RuntimeError: If the object type is unknown.
        RSADSAr   zunknown type of object: %rN)rE   r   r   r   RSAPrivateKeyr
   r   DSAPrivateKeyr   r   EllipticCurvePrivateKeyRuntimeErrorr   r1   r1   r2   r?   E  s$     
 
 

zKey.typec                 C   s:   |   dkr$dt| jjjd  S ddd|    S 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   asciirN   rO   )r  r  N)r?   
_secToNistr   ro   r   rF   r   r1   r1   r2   sshTypeZ  s    zKey.sshTypec                 C   s,   | j dkrdS |  dkr$| j jjS | j jS )zv
        Return the size of the object we wrap.

        @return: The size of the key.
        @rtype: L{int}
        Nr   r   )r   r?   ro   r   r   r1   r1   r2   sizej  s
    

zKey.sizec              	   C   sV  t | jtjr&| j }|j|jdS t | jtjrj| j }|jj|jj|j	|j
|jt|j|j
dS t | jtjr| j }|j|jj|jj
|jjdS t | jtjr| 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rB| j }|jj|jj|j|  dS td| jf dS )	z_
        Return the values of the public key as a dictionary.

        @rtype: L{dict}
        r   r   r   )rm   rV   rT   rR   rS   r   )rm   rV   rr   ro   zUnexpected key type: %sN)rE   r   r   r   r   rf   re   r  Zprivate_numbersrj   rR   rS   r   r
   r   rV   rW   rT   r  rm   r   r   r  r  r   r  )r   Znumbersr1   r1   r2   rL   w  sV    

	



zKey.datac                 C   s   |   }|  }|dkr>tdt|d  t|d  S |dkrtdt|d  t|d  t|d	  t|d
  S | jjjd d }t|d t|d dd  tdt	|d | t	|d
 |  S dS )aG  
        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

        @rtype: L{bytes}
        r  rN   re   rf   r  rO   rR   rS   rT   rV      r   ro   iN   rm   )
r?   rL   r   r   r   r   ro   r   r   r   )r   r?   rL   Z
byteLengthr1   r1   r2   rb     s(    "zKey.blobc                 C   s
  |   }|  }|dkrvtdt|d  t|d  t|d  t|d  t|d  t|d  S |d	krtd
t|d  t|d  t|d  t|d  t|d  S t|d t|d  t|d  t|d  S dS )a  
        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.
        r  rN   rf   re   rj   rx   rR   rS   r  rO   rT   rV   rm   ro   rr   N)r?   rL   r   r   r   )r   r?   rL   r1   r1   r2   privateBlob  s:     zKey.privateBlobc                 C   s^   t |tr|d}t| d| f d}|dkr@td|f |jjdkrT||S | S 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.
        @type extra: L{bytes} or L{unicode} or L{None}

        @rtype: L{bytes}
        rC   z_toString_%sNzunknown key type: %srD   )rE   r%   rF   rH   rI   r+   rJ   rK   )r   r?   extrarM   r1   r1   r2   toString  s    

zKey.toStringc              
      s  |   }|  r~|  dkrF|s$d}| jtjjtjjd | 	 S t
|  dd |sbd}|  d   d | 	 S |  dkr|st }n
t|}| jtjjtjj|S dd|  ddfg}|  dkr6|d	 |d
  }}d|d |d |d |||d |d  |d |d  |d f	}n$d|d	 |d
 |d |d |d f}t }tt |D ]\}	}
||	t|
 qpt|}|rrtd}ddd t |D }|d}|!d |!d| d  t"|| # }t"|| | # }|| dd }dt$|d  }|t%|| d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 dS ) a  
        Return a public or private OpenSSH string.  See
        _fromString_PUBLIC_OPENSSH and _fromString_PRIVATE_OPENSSH for the
        string formats.  If extra is present, it represents a comment for a
        public key, or a passphrase for a private key.

        @param extra: Comment for a public key or passphrase for a
            private key
        @type extra: L{bytes}

        @rtype: L{bytes}
        r   r   r      
s   -----BEGIN r	  s    PRIVATE KEY-----r  rR   rS   r   rf   re   rj   rX   rx   rT   rV   rm   r   r   c                 S   s   g | ]}d t |f qS )z%02X)r   r   r1   r1   r2   rp   c  s     z)Key._toString_OPENSSH.<locals>.<listcomp>r   s   DEK-Info: DES-EDE3-CBC,Nr   r   c                    s   g | ]} ||d   qS )@   r1   r   r   r1   r2   rp   v  s     r  s	   -----END )0rL   r   r?   r   Zpublic_bytesr	   EncodingZOpenSSHZPublicFormatr   encodebytesrb   replacer  NoEncryptionZBestAvailableEncryptionprivate_bytesPEMPrivateFormatTraditionalOpenSSLr   rF   r   Sequencer#   	itertoolsr   ZsetComponentByPositionZInteger
berEncoderr    ZsecureRandomr!   r   r   r   r   chrr   r   r   r   r   r   	encryptorr   r   r   )r   r  rL   r!  r   rR   rS   ZobjDataZasn1Sequenceindexr   Zasn1Datar   Zhexivr   r   ZencKeyZpadLenr1   r  r2   _toString_OPENSSH)  s    

 




"zKey._toString_OPENSSHc                 C   s  |   }|  }|  r|dkrftdddt|d dd gdt|d	 dd gggg}n|d
krt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|f dt|	dd d S |dkr|d |d  }}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d gg	ggS |d
krt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$|f dS )%z
        Return a public or private LSH key.  See _fromString_PUBLIC_LSH and
        _fromString_PRIVATE_LSH for the key formats.

        @rtype: L{bytes}
        r  r   r   r   rf   rP   Nr   re   r  r   r   rR   r   rS   r   rT   r   rV   r   r   r  r      }r   r   r   rj      arX      b   crx   r   rm   zunknown key type %s')
rL   r?   r   r   Zpackr   r   r+   r  r  )r   rL   r?   r   rR   rS   r1   r1   r2   _toString_LSH{  sp    




zKey._toString_LSHc                 C   s   |   }|  s|  dkrF|d |d |d |d |d |d f}n.|  dkrt|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}
        r  re   rj   rf   rx   rR   rS   r  rT   rV   rm   r   N)	rL   r   r?   r   r   r  r   mapr   )r   rL   valuesr1   r1   r2   _toString_AGENTV3  s     zKey._toString_AGENTV3c                 C   s  |   }|dkr6| j|t t }t|}n>|dkrx| j|t }t	|\}}tt
|dt
|d }n|dkrt|  }|dkrt }n|dkrt }nt }| j|t|}	t	|	\}}t
|}
t
|}t |
d tkrt|
d }n|
d }|d@ r d	|
 }
t |d tkr@t|d }n|d }|d@ rZd	| }tt|
t| }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.
        r  r     r        r          )r?   r   signr   PKCS1v15r   SHA1r   r   r   r   r  SHA256SHA384SHA512r   ECDSAstrr   r  )r   rL   rc   ZsigZretrsr   hashSize	signaturer9   ZsbZrcompZscompr1   r1   r2   r1    s>    




zKey.signc                 C   s  t |dkrdt| }}nt|\}}||  kr<dS |  }|dkr| j}|  sb| }t|d |t	
 t f}n|dkrt|d }t|dd d	}t|dd d	}	t||	}| j}|  s| }||t f}n|d
krt|d }t|d\}
}}t|
d	}t|d	}	t||	}| j}|  sN| }|  }|dkrjt }n|dkr~t }nt }||t|f}z|j|  W n tk
r   Y dS X dS dS )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.
        (   rO   Fr  r   r  Nr,  Zbigr   rD   r-  r.  T)r   r   r   rZ   r  r?   r   r   r]   r   r2  r   r3  r   r   r  r4  r5  r6  r   r7  verifyr   )r   r<  rL   ZsignatureTyperc   r   argsZconcatenatedSignaturer9  r:  ZrstrZsstrrd   r   r;  r1   r1   r2   r>    sZ    









z
Key.verify)NN)NN)NNNN)N)N)N)'r-   r.   r/   r0   classmethodrB   r;   rg   ry   r}   r   r   r   r   rG   rs   rt   rw   r   r   r   r   r   r   r5   r6   r  r?   r  r  rL   rb   r  r  r#  r(  r+  r1  r>  r1   r1   r1   r2   r8   j   s^   )
:
6

 

#
0
,"
		)
(;,/
R4?r8      c              
   C   s   |   jdd |  sPtjd|t d}|jtjj	tj
jt d}| | | d,}tj| dt d}t|W  5 Q R  S Q R X 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)ZignoreExistingDirectoryi  )Zpublic_exponentr   r   )encodingr  Zencryption_algorithmr9   N)Zpasswordr   )parentmakedirsexistsr   Zgenerate_private_keyr   r  r	   r  r  r  r  r  Z
setContentr:   r   r<   r8   )locationr   Z
privateKeyZpemZkeyFiler1   r1   r2   _getPersistentRSAKeyF  s(    
rG  )rA  )Qr0   Z
__future__r   r   r   r  Zhashlibr   r   r   Zcryptography.exceptionsr   Zcryptography.hazmat.backendsr   Zcryptography.hazmat.primitivesr   r	   Z)cryptography.hazmat.primitives.asymmetricr
   r   r   r   Z,cryptography.hazmat.primitives.serializationr   r   Zcryptographyr   Z/cryptography.hazmat.primitives.asymmetric.utilsr   r   ImportErrorr   r   Z&cryptography.hazmat.primitives.ciphersr   r   r   Zpyasn1.errorr   Zpyasn1.typer   Zpyasn1.codec.berr   r   r   r  Ztwisted.conch.sshr   r   Ztwisted.conch.ssh.commonr   r   Ztwisted.pythonr    Ztwisted.python.compatr!   r"   r#   r$   r%   r&   r'   r{   r(   r  Ztwisted.python.constantsr)   r*   Z	SECP256R1Z	SECP384R1Z	SECP521R1r`   r
  	Exceptionr+   r3   r4   r5   objectr8   rG  r1   r1   r1   r2   <module>   s`   (
	         e